Abhinandan's Blog
ABHINANDAN ARYAL

anudwigna[at]gmail.com

HOME

Setting up ASP Identity with dapper

May 02, 2020

C# ASP.NET Core Dapper

Entity Framework core has been the default data access technology for ASP Core Identity. All the tutorials and resources show how to implement ASP CORE Identity using EF Core. However, the ASP Identity is a very flexible framework and it allows other ORMs like Dapper to be integrated with it. In this article, I will walk you through the process of creating an ASP Core application in which we will be able to manage Users along with their authentication and authorization process and the ORM for ASP Identity will be Dapper.

Creation of an ASP CORE Web Application Project

Let us first create an ASP Core Web Application Project. For this, fire up your Visual Studio. I will be using Visual Studio 2019 (Community Edition) and .NET Core 3.1. Create a new ASP Core Web Application. I like to go with MVC based web application reather than razor pages version.

The project structure for newly created ASP Core (MVC) Web Application will be like:

Newly created ASP MVC Core Project Structure

Let's start by running the scripts to generate the tables in database which will hold the information related to users, their roles and claims as well. The tables will be the same as generated by EF Core. The link to the scripts can be found here.

Dapper Configuration

Go to the nuget manager for the project and install dapper. Now, lets create a class to manage the connection to database. Create a class named "DbConnection" in the root of the project. Copy and paste the following code inside this class.

using Microsoft.Extensions.Configuration;
using System.Data.SqlClient;

namespace aspcore_identity_without_efcore
{
    public interface IDbConnection
    {
        public SqlConnection GetConnection { get; }
    }
    public class DbConnection : IDbConnection
    {
        IConfiguration Configuration;

        public DbConnection(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public SqlConnection GetConnection 
        {
            get {
                var connectionString = Configuration.GetConnectionString("DefaultConnection");
                return new SqlConnection(connectionString);
            }
        }
    }
}

Above code is pretty much straight forward. Here a connection string named "DefaultConnection" is being pulled from appsettings.json and we are returning a SqlConnection from this class in the form of a property named "GetConnection". This class will be referenced by our repositories to get the connection to the database. The same connection will also be provided to Dapper in repository classes.

Now, let's add some models for Identity. Create a class named "IdentityModels" inside "Models" folder and paste the folowing code.

using Microsoft.AspNetCore.Identity;

namespace aspcore_identity_without_efcore.Models
{
    public class IdentityModels
    {
    }

    public class ApplicationUserRole : IdentityRole { }

    public class ApplicationUser : IdentityUser { }
}

Again, Create a folder named "Identity" in the root of the project. Here, we will create some classes that implement the Identity logic. First, create a class called "CustomUserStore" and implement as it is given here. Also, create another class called "CustomRoleStore" and implement as it is given here. With the implementation of these classes, we are ready to call methods of ASP Identity. Now, register these newly created classes in ASP Core DI system by pasting the following code inside "ConfigureServices" method of "Startup" Class.

services.AddIdentity<ApplicationUser, ApplicationUserRole>()
        .AddUserStore<CustomUserStore>()
        .AddRoleStore<CustomRoleStore>()
        .AddDefaultTokenProviders();

Here I have implemented only User store but not the Role store as it is out of the scope of this article.

Configuring Controllers

Now, create a controller named "AuthController" inside "Controllers" folder. Inside this controller, implement logic for user autentication. So, create an action called "Register" and a view for it as well.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using aspcore_identity_without_efcore.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Vereyon.Web;

namespace aspcore_identity_without_efcore.Controllers
{
    public class AuthController : Controller
    {
        private UserManager<ApplicationUser> _userManager;
        IFlashMessage _flashMessage;

        public AuthController(UserManager<ApplicationUser> userManager, IFlashMessage flashMessage)
        {
            _userManager = userManager;
            _flashMessage = flashMessage;
        }

        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Register()
        {
            ViewBag.ErrorMessage = null;
            return View(new RegisterUser());
        }


        [HttpPost]
        public async Task<IActionResult> Register(RegisterUser user)
        {
            try
            {
                if (string.IsNullOrEmpty(user.Username))
                    throw new Exception("The username cannot be empty!");

                if (string.IsNullOrEmpty(user.Password))
                    throw new Exception("The password cannot be empty!");

                if (user.Password != user.ConfirmPassword)
                    throw new Exception("The Passwords do not match!");

                var theUser = new ApplicationUser()
                {
                    UserName = user.Username
                };

                await _userManager.CreateAsync(theUser, user.Password);

                return View(new RegisterUser());
            }
            catch(Exception ex)
            {
                _flashMessage.Danger(ex.Message);
                return View(user);
            }
        }
    }
}

Now, we can see that the user can be registered. Similarly, implement the Login Functionality as well.

All the source code for this article can be found here.