Working with Roles in ASP.NET Identity for MVC

Sheonarayan
Posted by in ASP.NET MVC category on for Advance level | Points: 250 | Views : 377280 red flag
Rating: 5 out of 5  
 7 vote(s)

In this article, we are going to learn how to create a role, modify role, delete role and manage a role for a particular user using ASP.NET Identity in ASP.NET MVC. The entire source code can be downloaded from GitHub.
Recommendation
Read Working with Roles in ASP.NET MVC 4+ before this article.

Introduction

ASP.NET Identity provides almost all feature required to perform authentication and authorization for an ASP.NET application however adding a new role, assigning it to a particular user seems to be lost in all these features. In this article, we will learn everything that is required to create a new role, modify role, delete it and manage a role for a particular user in ASP.NET MVC 5+.

Download the complete source code of this article is available at GitHub.

Assumption

Here we are assuming that reader has basic knowledge of ASP.NET MVC and he/she knows how the view, controller and Entity framework works. In case you do not know basics of ASP.NET MVC, please read beginners level articles from ASP.NET MVC articles of DotNetFunda.com.

Lets get started managing Roles in ASP.NET Identity 

By default when an ASP.NET MVC default application is run and auto migration is on, registering a user automatically creates following table (starting with Asp....) in the database where
  1. AspNetRoles - stores roles information contains Id and Name columns
  2. AspNetUsers - stores users information contains Id, UserName, PasswordHash, SecurityStamp and Discriminator columns
  3. AspNetUserRoles - stores user and role id contains UserId and RoleId columns
Explanations of other tables are not given here as those of out of context of this article.



As by default we do not get default Model class for ASP.NET Identity related database tables, so we may need to create our controller and view manually. In this case, we have a separate controller and view folder for Roles.

Application assumption

Here, our assumption is that we already have an IdentityModels.cs class in the Models folder whose code looks like below (in ASP.NET MVC 5, it gets created automatically).
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
    public class ApplicationUser : IdentityUser
    {
    }

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
            : base("DefaultConnection")
        {
        }
    }
In all the Action methods of the RolesController, no authorize attribute has been (to check for the admin user who is authorized to deal with Roles) used just for the shake of clarity and make the code snippet easily readable and understandable.

Creating a new Role with ASP.NET Identity

To create a new Role, we have below view and the code snippet for this is below.


@{
    ViewBag.Title = "Create";
}

<h2>Create Role</h2>
@Html.ActionLink("List Roles", "Index") | @Html.ActionLink("Manage User Role", "ManageUserRoles")
<hr/>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <div>
        Role name
    </div>
    <p>
        @Html.TextBox("RoleName")
    </p>
    <input type="submit" value="Save" />
}

In the above code snippet, we have a simple TextBox named "RoleName" and some general form related code, please note that we do not have a @model directive here. The controller methods looks like below.

Namespace required in order to work with Roles are below

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
Controller method for Create view looks like below
        // GET: /Roles/Create
        public ActionResult Create()
        {
            return View();
        }

        //
        // POST: /Roles/Create
        [HttpPost]
        public ActionResult Create(FormCollection collection)
        {
            try
            {
                context.Roles.Add(new Microsoft.AspNet.Identity.EntityFramework.IdentityRole()
                {
                    Name = collection["RoleName"]
                });
                context.SaveChanges();
                ViewBag.ResultMessage = "Role created successfully !";
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

The first Create method simply returns the Create view and second Create method accepts FormCollection object as parameter and uses context object (instance of ApplicationDbContext) to add a Role to the Roles collection. Note that despite our roles table in the database name is AspNetRoles, the model class name is IdentityRole (part of ASP.NET Identity provider). Calling SaveChanges method saves the new role into the database.

Read my ASP.NET MVC How to Tips & Tricks eBook here.

Listing Roles with ASP.NET Identity



To list roles using ASP.NET Identity, we have below view code.
@model IEnumerable<Microsoft.AspNet.Identity.EntityFramework.IdentityRole>
@{
    ViewBag.Title = "Index";
}

<h2>Roles Listing </h2>

@Html.ActionLink("Create New Role", "Create") | @Html.ActionLink("Manage User Role", "ManageUserRoles")
<hr/>
<div>
    @foreach (var role in Model)
{
    <p><strong>@role.Name | </strong> 
    <span onclick="return confirm('Are you sure to delete?')"><a href="/Roles/Delete?RoleName=@role.Name" class="delLink" style="color:red;">Delete</a></span> | 
    @Html.ActionLink("Edit", "Edit", new { roleName = @role.Name })
    </p>
}
</div>
In the above code snippet, the model of this view is IdentityRole and in foreach loop, all the role from the Roles collection are being listed. While listing roles, we have also created link to Delete and Edit a particular Role.

The controller method to list ASP.NET Identity role looks like below

        public ActionResult Index()
        {
            var roles = context.Roles.ToList();
            return View(roles);
        }

In the above code snippet, we are simply getting the Roles collection from ApplicationDbContext and returning to the View.

Deleting a Role using ASP.NET Identity

Clicking Delete link from the list of Roles deletes a particulrole from the database, and here is the action method of the RolesController.

public ActionResult Delete(string RoleName)
        {
            var thisRole = context.Roles.Where(r => r.Name.Equals(RoleName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
            context.Roles.Remove(thisRole);
            context.SaveChanges();
            return RedirectToAction("Index");
        }
Where we are getting the selected Role from the database and calling Remove method of the Roles collection. Calling SaveChanges method of the ApplicationDbContext object deletes the selected role from the database.

Editing Role using ASP.NET Identity





To edit role, we have above View and the code looks like below

@model Microsoft.AspNet.Identity.EntityFramework.IdentityRole
@{
    ViewBag.Title = "Edit";
}

<h2>Edit Role</h2>

@Html.ActionLink("List Roles", "Index") | @Html.ActionLink("Manage User Role", "ManageUserRoles")
<hr />
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    @Html.HiddenFor(model => model.Id)
    <div>
        Role name
    </div>
    <p>
        @Html.TextBoxFor(model => model.Name)
    </p>
    <input type="submit" value="Save" />
}
In the above view code, IdentityRole class is our model whose field is getting populated in the form to edit the role. 

The controller Edit methods looks like below
        //
        // GET: /Roles/Edit/5
        public ActionResult Edit(string roleName)
        {
            var thisRole = context.Roles.Where(r => r.Name.Equals(roleName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();

            return View(thisRole);
        }

        //
        // POST: /Roles/Edit/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(Microsoft.AspNet.Identity.EntityFramework.IdentityRole role)
        {
            try
            {
                context.Entry(role).State = System.Data.Entity.EntityState.Modified;
                context.SaveChanges();

                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

In the above code snippet, the first method accept roleName as parameter and based on that we retrieve the role from the database and returns to the View.

The second method accept IdentityRole as parameter and update the record to the database.

Managing roles for a particular User in ASP.NET Identity


To manage role for a particular user in ASP.NET Identity, we have below view that has more than one form to 
  1. Add a role to the user
  2. Get roles for a user and
  3. Delete/Detach a user from a particular role



The code for the above view looks like below

@{
    ViewBag.Title = "ManageUserRoles";
}

<h2>Manage User Roles</h2>
@Html.ActionLink("Create New Role", "Create") | @Html.ActionLink("Manage User Role", "ManageUserRoles")
<hr/>

<h2>Role Add to User</h2>

@using (Html.BeginForm("RoleAddToUser", "Roles"))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <p>
        Username : @Html.TextBox("UserName")
        Role Name: @Html.DropDownList("RoleName", (IEnumerable <SelectListItem>) ViewBag.Roles, "Select ...")

    </p>

    <input type="submit" value="Save" />
}
<hr/>
<h3>Get Roles for a User</h3>
@using (Html.BeginForm("GetRoles", "Roles"))
{
    @Html.AntiForgeryToken()
    <p>
        Username : @Html.TextBox("UserName")
        <input type="submit" value="Get Roles for this User" />
    </p>
}

@if (ViewBag.RolesForThisUser != null)
{
    <div style="background-color:yellow;">
        <h3>Roles for this user </h3>
        <ol>
            @foreach (string s in ViewBag.RolesForThisUser)
            {
                <li>@s</li>
            }
        </ol>
    </div>
}

<hr />
<h3>Delete A User from a Role</h3>

@using (Html.BeginForm("DeleteRoleForUser", "Roles"))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <p>
        Username : @Html.TextBox("UserName")
        Role Name: @Html.DropDownList("RoleName", (IEnumerable<SelectListItem>)ViewBag.Roles, "Select ...")

    </p>

    <input type="submit" value="Delete this user from Role" />
}

The controller ManageUserRoles method looks like this

 public ActionResult ManageUserRoles()
        {
            // prepopulat roles for the view dropdown
            var list = context.Roles.OrderBy(r => r.Name).ToList().Select(rr => 

new SelectListItem { Value = rr.Name.ToString(), Text = rr.Name }).ToList();
            ViewBag.Roles = list;   
            return View();
        }
Where we are simply getting the Roles list and setting into the Roles ViewBag that will be used to populate the Roles DropDown in the view.

Adding a role to the User using ASP.NET Identity


(DO not get confused and do not worry too much about sentence formation, grammar or proper use of words :), you can also say Adding a user to the Role. Just have fun with this childish title :D)

Where the first Form has simply a UserName textbox and a RoleName dropdown list that contains current Roles from the database. Submitting the form sends form data to RoleAddToUser action method of the RolesController.

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult RoleAddToUser(string UserName, string RoleName)
        {
            ApplicationUser user = context.Users.Where(u => u.UserName.Equals(UserName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
            var account = new AccountController();
            account.UserManager.AddToRole(user.Id, RoleName);
            
            ViewBag.ResultMessage = "Role created successfully !";
            
            // prepopulat roles for the view dropdown
            var list = context.Roles.OrderBy(r => r.Name).ToList().Select(rr => new SelectListItem { Value = rr.Name.ToString(), Text = rr.Name }).ToList();
            ViewBag.Roles = list;   

            return View("ManageUserRoles");
        }
In the above method, we are getting UserName and RoleName as parameter.

UserName is being used to get the ApplicationUser from context.Users collection. Then AccountController object is being used to access the UserManager object property and call its AddToRole method by passing UserId from the ApplicationUser object and RoleName coming in from the form.

Next few lines of codes are just to list the roles in the DropDown list again as we are returning to the same (ManageUserRoles) view again.

Getting Roles for a user in ASP.NET Identity




In the second form, we have a UserName textbox and a button. Clicking button submits the form to the GetRoles action method of the RolesController.

The GetRoles controller method looks like below

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult GetRoles(string UserName)
        {            
            if (!string.IsNullOrWhiteSpace(UserName))
            {
                ApplicationUser user = context.Users.Where(u => u.UserName.Equals(UserName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
                var account = new AccountController();

                ViewBag.RolesForThisUser = account.UserManager.GetRoles(user.Id);

                // prepopulat roles for the view dropdown
                var list = context.Roles.OrderBy(r => r.Name).ToList().Select(rr => new SelectListItem { Value = rr.Name.ToString(), Text = rr.Name }).ToList();
                ViewBag.Roles = list;            
            }

            return View("ManageUserRoles");
        }
In the above code snippet, we are getting the ApplicationUser object using the UserName. Then AccountController object is being used to get the Roles for that particular UserName using its id.

Deleting a User from a Role

(Another title, have fun :D)

In the third form, we have a UserName textbox and  RoleName dropdown list. Clicking button submits the form to DeleteRoleForUser action method and below is the code snippet for that.

       [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteRoleForUser(string UserName, string RoleName)
        {
            var account = new AccountController();
            ApplicationUser user = context.Users.Where(u => u.UserName.Equals(UserName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();

            if (account.UserManager.IsInRole(user.Id, RoleName))  
            {
                account.UserManager.RemoveFromRole(user.Id, RoleName);
                ViewBag.ResultMessage = "Role removed from this user successfully !";
            }
            else
            {
                ViewBag.ResultMessage = "This user doesn't belong to selected role.";
            }
            // prepopulat roles for the view dropdown
            var list = context.Roles.OrderBy(r => r.Name).ToList().Select(rr => new SelectListItem { Value = rr.Name.ToString(), Text = rr.Name }).ToList();
            ViewBag.Roles = list;

            return View("ManageUserRoles");
        }

In the above code snippet, we are getting ApplicationUser and then checking whether this user  belongs to the selected Role or not (using AccountController object), if it is then calling the RemoveFromRole method by passing UserId and RoleName parameter that removes the user from the role.

Source code: The entire source code for this article can be downloaded from GitHub directly, also you are most welcome to enhance or improve it by participating in it on GitHub.  

Conclusion

In this article, we learnt how to develop User Interface to create a new Role, Edit a role, Delete a role, View roles attached to a particular user and manage a role for a particular user using ASP.NET Identity in ASP.NET MVC.

Hope this article would be useful. 

If you liked this article, please share this to your friends and colleagues and do let us know your comment or feedback. Thanks for reading.

Reference


  • http://www.asp.net/identity
Page copy protected against web site content infringement by Copyscape

About the Author

Sheonarayan
Full Name: Sheo Narayan
Member Level: HonoraryPlatinum
Member Status: Administrator
Member Since: 7/8/2008 6:32:14 PM
Country: India
Regards, Sheo Narayan http://www.dotnetfunda.com

Ex-Microsoft MVP, Author, Writer, Mentor & architecting applications since year 2001. Connect me on http://www.facebook.com/sheo.narayan | https://twitter.com/sheonarayan | http://www.linkedin.com/in/sheonarayan

Login to vote for this post.

Comments or Responses

Posted by: Markabarmi on: 11/20/2014 | Points: 25
Hi all great tutorial.I have issues with trying to retrieve the users roles and add roles to the user. I have made a small change and am populating the userName box with a dropdown list of users that are in the DB http://prntscr.com/588aa0. If i try to retrieve a users role i get the following error http://prntscr.com/588arm. and if I try to add a role to a user I get this error http://prntscr.com/588b1c.
Any help would be awersome :)
Posted by: Taqwa on: 12/1/2014 | Points: 25
thanks alot for this great tutorial,
I faced a problem while doing the first step crate role.
Error 1 The name 'context' does not exist in the current context

can you please help me in this problem thanks alot.
Posted by: rudolfterppede-29355 on: 1/4/2015 | Points: 25
Great tutorial
I install in
Clobal.asax.cs to get superadmin in DB
        protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

var context = new ApplicationDbContext();
if (!context.Users.Any(user => user.UserName == "superadmin@terppe.de"))
{
var userStore = new UserStore<ApplicationUser>(context);
var userManager = new UserManager<ApplicationUser>(userStore);
var applicationUser = new ApplicationUser() {UserName = "superadmin@terppe.de"};
userManager.Create(applicationUser, "asdn6g7");

var roleStore = new RoleStore<IdentityRole>(context);
var roleManager = new RoleManager<IdentityRole>(roleStore);
roleManager.Create(new IdentityRole("Security"));

userManager.AddToRole(applicationUser.Id, "Security");
}

FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}

and in _Layout.cshtml
                <ul class="nav navbar-nav">
<li>@Html.ActionLink("Start", "Index", "Home")</li>
<li>@Html.ActionLink("Info", "About", "Home")</li>
<li>@Html.ActionLink("Kontakt", "Contact", "Home")</li>
<li>
@Html.ActionLink("AdminArea", "AdminArea", "Home")
<ul>
@if (User.IsInRole("Security"))
{
<li>@Html.ActionLink("Security", "Index", "Roles")</li>
}
</ul>
</li>
So I'am able to configure the following Users if registered with Roles
Hope this helps
Posted by: Net4u on: 11/26/2015 | Points: 25
Hi

How to retrieve after login the username and the role(s) in a "global" way, for being available application wide (e.g. for filtering data in specific views based on username, and/or restricting acces to certain views by role and/or username)? I mean at a scenario like an admin have to see all views and all data in any view, but for example let say an medicine to have access only to designed views and to see only his patients.
L.E.
And by the way, how to implement a solution to assign roles with checkboxes (a way for one to many association)?
Posted by: Agohil on: 5/16/2016 | Points: 25
Hi, good tutorial.

I am new to c# mvc and stuck with this problem.

When creating the controller method for create (context.Roles.Add). it does not recognise 'context' becomes underlined red. "The name context does not exist in current context" I am unsure what context to use.

Any advice is appreciated.


Posted by: Rogersb on: 6/9/2016 | Points: 25
Hi, the code DOES NOT WORK. Its great and helpful how you explain it, but if you download from github the code will not run, you cannot assign a role to a user. the method is missing to assign a role, and the author makes a mistake in the RolesController around line 101 to 103.

The original code also has a minor glitch in the web.config, pointing to his computer that the user has to point to their own system.

but if you run the code you can create new roles, but cannot assign to any user. Would you please take a look?
Posted by: Sheonarayan on: 6/9/2016 | Points: 25
Hi Rogersb,

Thanks!

Entity Framework and the way it works are keep changing, this article code was working at the time of writing this article. Now in order to add roles to the user, you can use below code or as suggested by others (Facebook comment and others)

var um = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var idResult = um.AddToRole(user.Id, RoleName);


Hope this will help.

Enjoy
Posted by: Dereje on: 8/24/2017 | Points: 25
After Creating User and role When i Asiign a user to roles i get the follwing error
please somebody help me
thank you
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Roles/RoleAddToUser

Login to post response

Comment using Facebook(Author doesn't get notification)