Adding Roles to Registration Razor Page in ASP.NET Core

Introduction

 
This article is the continuation of the article “Registration Razor Page in ASP.NET Core Razor Pages Web Application”. In this article, we will be creating different roles for our application. We will work on different kinds of roles that we can assign to each user using this application.
 

Creating Roles for the application

 
We have two types of users in the application I created in the previous article. We will create two types of users to login through the registration form created in the previous article. The users will be admin and customer users. As we worked on the create function to create a new user, now we will work on different kinds of roles that we can assign to each user trying to create an account in this particular application.
 
Let’s add two roles in our database. In order to add roles, we can create a static class. To create a class, right-click on the project, click on Add and then select folder. This will add a new folder named utility.
 
Now right click on the utility folder. Click on add, then select class option to add a static class named sd.
 
 
 
This class will contain all the constants:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Threading.Tasks;  
  5.   
  6. namespace SparkAutomation.Utility  
  7. {  
  8.     public class SD  
  9.     {  
  10.         public const string AdminEndUser = "Admin";  
  11.         public const string CustomerEndUser = "Customer";  
  12.   
  13.     }  
  14. }  
Next, we add constants to different types of roles for the website. The two constants are AdminEndUser and CustomerEndUser.
 
Now in our application, if we want to login as admin we can reference to AdminEndUser and if we want to login as a customer we can reference to CustomerEndUser inside a static class.
 
Now inside the registration form, when a new user is added we can make them admin for a default scenario.
 
We can create a new user inside the post handler. Inside the post hander, we have to create an application user and we have to assign all of the properties as well such as username, email, name, address, city, postal code, and phone number.
  1. var user = new ApplicationUser   
  2.                 {   
  3.                     UserName = Input.Email,   
  4.                     Email = Input.Email,  
  5.                     Name = Input.Name,  
  6.                     Address = Input.Address,  
  7.                     City = Input.City,  
  8.                     PostalCode = Input.PostalCode,  
  9.                     PhoneNumber = Input.PhoneNumber  
  10.                 };  
Now once a user is created, we can create roles as well. In order to add roles, we have to get role manager using dependency injection. While saving changes inside database for any newly created use of database object as well.
  1. private readonly RoleManager<IdentityRole> _roleManager;  
  2. private readonly ApplicationDbContext _db;  
We have to add them inside RegisterModel constructor as follows.
  1. public RegisterModel(  
  2.             UserManager<IdentityUser> userManager,  
  3.             SignInManager<IdentityUser> signInManager,  
  4.             ILogger<RegisterModel> logger,  
  5.             IEmailSender emailSender,  
  6.             RoleManager<IdentityRole> roleManager,  
  7.             ApplicationDbContext db)  
  8.         {  
  9.             _userManager = userManager;  
  10.             _signInManager = signInManager;  
  11.             _logger = logger;  
  12.             _emailSender = emailSender;  
  13.             _db = db;  
  14.             _roleManager = roleManager;  
  15.         }  
Here, we are adding two read only properties inside dependency injection, which are roleManager and ApplicationDbContext.
 
Inside the post handler, when the user is created we are checking if the roles exist in the database or not. If the user does not exist, we can create it for both admin and customer using the below line of code.
  1. if (result.Succeeded)  
  2.                 {  
  3.                     if (!await _roleManager.RoleExistsAsync(SD.AdminEndUser))   
  4.                     {  
  5.                         await _roleManager.CreateAsync(new IdentityRole(SD.AdminEndUser));  
  6.                     }  
  7.   
  8.                     if (!await _roleManager.RoleExistsAsync(SD.CustomerEndUser))  
  9.                     {  
  10.                         await _roleManager.CreateAsync(new IdentityRole(SD.CustomerEndUser));  
  11.                     }  
When these lines gets executed, they will create new roles inside database. Once a role is create we can assign it to the user using below line of code.
  1. await _userManager.AddToRoleAsync(user,SD.AdminEndUser);  
We have to add the IdentityRole to the pipeline inside the startup.cs file so that the application will run properly.
  1. public void ConfigureServices(IServiceCollection services)  
  2.         {  
  3.             services.AddDbContext<ApplicationDbContext>(options =>  
  4.                 options.UseSqlServer(  
  5.                     Configuration.GetConnectionString("DefaultConnection")));  
  6.               
  7.             services.AddIdentity<IdentityUser,IdentityRole>()  
  8.                 .AddDefaultTokenProviders()  
  9.                 .AddDefaultUI()  
  10.                 .AddEntityFrameworkStores<ApplicationDbContext>();  
  11.             services.AddRazorPages().AddRazorRuntimeCompilation();   
  12.         }  
Now IdentityRole will be added and configured inside the application.
 
Register.cshml.cs
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel.DataAnnotations;  
  4. using System.Linq;  
  5. using System.Text;  
  6. using System.Text.Encodings.Web;  
  7. using System.Threading.Tasks;  
  8. using Microsoft.AspNetCore.Authentication;  
  9. using Microsoft.AspNetCore.Authorization;  
  10. using Microsoft.AspNetCore.Identity;  
  11. using Microsoft.AspNetCore.Identity.UI.Services;  
  12. using Microsoft.AspNetCore.Mvc;  
  13. using Microsoft.AspNetCore.Mvc.RazorPages;  
  14. using Microsoft.AspNetCore.WebUtilities;  
  15. using Microsoft.Extensions.Logging;  
  16. using SparkAutomation.Data;  
  17. using SparkAutomation.Models;  
  18. using SparkAutomation.Utility;  
  19.   
  20. namespace SparkAutomation.Areas.Identity.Pages.Account  
  21. {  
  22.     [AllowAnonymous]  
  23.     public class RegisterModel : PageModel  
  24.     {  
  25.         private readonly SignInManager<IdentityUser> _signInManager;  
  26.         private readonly UserManager<IdentityUser> _userManager;  
  27.         private readonly ILogger<RegisterModel> _logger;  
  28.         private readonly IEmailSender _emailSender;  
  29.         private readonly RoleManager<IdentityRole> _roleManager;  
  30.         private readonly ApplicationDbContext _db;  
  31.   
  32.         public RegisterModel(  
  33.             UserManager<IdentityUser> userManager,  
  34.             SignInManager<IdentityUser> signInManager,  
  35.             ILogger<RegisterModel> logger,  
  36.             IEmailSender emailSender,  
  37.             RoleManager<IdentityRole> roleManager,  
  38.             ApplicationDbContext db)  
  39.         {  
  40.             _userManager = userManager;  
  41.             _signInManager = signInManager;  
  42.             _logger = logger;  
  43.             _emailSender = emailSender;  
  44.             _db = db;  
  45.             _roleManager = roleManager;  
  46.         }  
  47.   
  48.         [BindProperty]  
  49.         public InputModel Input { getset; }  
  50.   
  51.         public string ReturnUrl { getset; }  
  52.   
  53.         public IList<AuthenticationScheme> ExternalLogins { getset; }  
  54.   
  55.         public class InputModel  
  56.         {  
  57.             [Required]  
  58.             [EmailAddress]  
  59.             [Display(Name = "Email")]  
  60.             public string Email { getset; }  
  61.   
  62.             [Required]  
  63.             [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]  
  64.             [DataType(DataType.Password)]  
  65.             [Display(Name = "Password")]  
  66.             public string Password { getset; }  
  67.   
  68.             [DataType(DataType.Password)]  
  69.             [Display(Name = "Confirm password")]  
  70.             [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]  
  71.             public string ConfirmPassword { getset; }  
  72.   
  73.             [Required]  
  74.             public string Name { getset; }  
  75.             public string Address { getset; }  
  76.             public string City { getset; }  
  77.             public string PostalCode { getset; }  
  78.   
  79.             [Required]  
  80.             public string PhoneNumber { getset; }  
  81.         }  
  82.   
  83.         public async Task OnGetAsync(string returnUrl = null)  
  84.         {  
  85.             ReturnUrl = returnUrl;  
  86.             ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();  
  87.         }  
  88.   
  89.         public async Task<IActionResult> OnPostAsync(string returnUrl = null)  
  90.         {  
  91.             returnUrl = returnUrl ?? Url.Content("~/");  
  92.             ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();  
  93.             if (ModelState.IsValid)  
  94.             {  
  95.                 var user = new ApplicationUser   
  96.                 {   
  97.                     UserName = Input.Email,   
  98.                     Email = Input.Email,  
  99.                     Name = Input.Name,  
  100.                     Address = Input.Address,  
  101.                     City = Input.City,  
  102.                     PostalCode = Input.PostalCode,  
  103.                     PhoneNumber = Input.PhoneNumber  
  104.                 };  
  105.                 var result = await _userManager.CreateAsync(user, Input.Password);  
  106.                 if (result.Succeeded)  
  107.                 {  
  108.                     if (!await _roleManager.RoleExistsAsync(SD.AdminEndUser))   
  109.                     {  
  110.                         await _roleManager.CreateAsync(new IdentityRole(SD.AdminEndUser));  
  111.                     }  
  112.   
  113.                     if (!await _roleManager.RoleExistsAsync(SD.CustomerEndUser))  
  114.                     {  
  115.                         await _roleManager.CreateAsync(new IdentityRole(SD.CustomerEndUser));  
  116.                     }  
  117.                     await _userManager.AddToRoleAsync(user,SD.AdminEndUser);  
  118.                     _logger.LogInformation("User created a new account with password.");  
  119.   
  120.                     var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);  
  121.                     code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));  
  122.                     var callbackUrl = Url.Page(  
  123.                         "/Account/ConfirmEmail",  
  124.                         pageHandler: null,  
  125.                         values: new { area = "Identity", userId = user.Id, code = code },  
  126.                         protocol: Request.Scheme);  
  127.   
  128.                     await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",  
  129.                         $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");  
  130.   
  131.                     if (_userManager.Options.SignIn.RequireConfirmedAccount)  
  132.                     {  
  133.                         return RedirectToPage("RegisterConfirmation"new { email = Input.Email });  
  134.                     }  
  135.                     else  
  136.                     {  
  137.                         await _signInManager.SignInAsync(user, isPersistent: false);  
  138.                         return LocalRedirect(returnUrl);  
  139.                     }  
  140.                 }  
  141.                 foreach (var error in result.Errors)  
  142.                 {  
  143.                     ModelState.AddModelError(string.Empty, error.Description);  
  144.                 }  
  145.             }  
  146.   
  147.             // If we got this far, something failed, redisplay form  
  148.             return Page();  
  149.         }  
  150.     }  
  151. }  
After running the application on the browser, we can create a new user and that user will be assigned a role.
 
 
 
 
Inside the database, we can see the AspNetUsers table has been populated with columns such as username, email, name, city, address, and postal code.
 
 
 
The table AspNetRoles also contains two rows. One for admin and another one for the customer. Here, two roles have been added, admin and customer.
 
 

Summary

 
In this article, we implemented a registration functionality for admin and user. We created two roles so when a new user is created, these roles are assigned to them accordingly. We made changes inside the register razor page to include identity roles for the newly created user.