Working with Roles in ASP.NET MVC 4+

Sheonarayan
Posted by in ASP.NET MVC category on for Beginner level | Points: 250 | Views : 290817 red flag
Rating: 4.5 out of 5  
 6 vote(s)

In this article, We'll look into how to create a new role, delete a role and attach a user to a specific role in ASP.NET MVC using default Role provider under System.Web.Security namespace.
Recommendation
Read Working with Roles in ASP.NET Identity for MVC before this article.

Introduction

Authentication (Login and Registration) is simple in ASP.NET MVC as the default project template provides all the necessary controller code, model and view to register and login. However adding roles and assigning roles to a particular user seems to be lost in all these stuffs. In this article, we will learn all that is related with Roles for a particular user in ASP.NET MVC 4.

Objective

The objective of this article is to explain how to work with Roles in ASP.NET MVC 4 +.

Assumption

Here we are assuming that we have used the default ASP.NET MVC template (ASP.NET MVC 4  Web Application project type and Internet Application template) that automatically creates a database for us when we try to register for the first time and the default database tables it creates for roles are following


  1. webpages_Roles
  2. webpages_UserInRoles

Creating a new role in ASP.NET MVC

In order to create a new Role, the default template doesn't provide any UI, so we have to build it our self. Below is the simple UI we have built in Razor under Views/Account folder (In fact all views we are going to work with in this article are in this folder). In this case we have used a different Layout page as we do not want the default website Layout to appear.

@{
    ViewBag.Title = "RoleCreate";
    Layout = "~/Views/Shared/_LayoutAdmin.cshtml";
}
<div class="spacerBody">
    <p>&nbsp;</p>
    @Html.ActionLink("Roles", "RoleIndex") | @Html.ActionLink("Add Role to User", "RoleAddToUser")
<h2>Role Create</h2>

@using(Html.BeginForm()){
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

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

Picture - 1

Notice that we have a simple TextBox in the above View with the name as  "RoleName" that we are going to use to create a new Role into our database.

Below are two methods in our AccountController.cs responsible for creating a new Role.

        [Authorize(Roles = "Admin")]
        public ActionResult RoleCreate()
        {
            return View();
        }

        [Authorize(Roles = "Admin")]
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult RoleCreate(string RoleName)
        {
            
                Roles.CreateRole(Request.Form["RoleName"]);
                // ViewBag.ResultMessage = "Role created successfully !";
            
            return RedirectToAction("RoleIndex", "Account");
        }

The first method simply renders the view provided the logged in user has Roles as "Admin" assigned to the database (because of Authorize attribute in this method). So to get started first go to your database table "webpages_Roles" and insert and "Admin" role then map this role to the user id you are logged in with in the "webpages_UsersInRoles" table.



In above case, I am logged in to the application as "SheoNarayan" that has UserId as "2" in the "UserProfile" table that is created by default by ASP.NET MVC project.

Now when Save button is clicked in Picture - 1, the 2nd method of the above code snippet fires and calls the "Roles.CreateRole" method to create a role that is entered into the Textbox.

Listing Roles in ASP.NET MVC

To list roles created in ASP.NET MVC, we have created another view called "RoleIndex" and here is the Razor code for this.

@{
    ViewBag.Title = "Role Listing";
    Layout = "~/Views/Shared/_LayoutAdmin.cshtml";
}
<p>&nbsp;</p>
<div class="spacerBody">
    @Html.ActionLink("Create New Role", "RoleCreate") | @Html.ActionLink("Add Role to User", "RoleAddToUser")
<h2>Role Index</h2>
    <div class="table">
        
    
@foreach (string s in Model)
{
    <div class="tr">
        <div class="td">
            @s
        </div>
        <div class="td">
            <span onclick="return confirm('Are you sure to delete?')">
        <a href="/Account/RoleDelete?RoleName=@s" class="delLink"><img src="/images/deleteicon.gif" alt="Delete" class="imgBorder0" /> Delete</a>
                           </span>
        </div>
    </div>
}
        </div>
</div>




In this view, we are simply looping through the Model we are receiving from the controller. The controller method that is responsible to render all the roles are below.
        [Authorize(Roles = "Admin")]
        public ActionResult RoleIndex()
        {
            var roles = Roles.GetAllRoles();
            return View(roles);
        }

The above code simply executes Roles.GetAllRoles() method that gives all roles from the webpages_Roles database table in the form of string array and returns to the view. The same is being used to list the roles on the view.

You must have noticed that we have also added a Delete link against each Role so that we can delete a role too. The Delete link passes the Role name as querystring to the RoleDelete method of the controller, lets see that too.

Delete a Role in ASP.NET MVC

To delete a role, we have just created a method in the controller named "RoleDelete" and making sure that it gets executed only when an Admin user is trying to browse it.

        [Authorize(Roles = "Admin")]
        public ActionResult RoleDelete(string RoleName)
        {
            
                Roles.DeleteRole(RoleName);
                // ViewBag.ResultMessage = "Role deleted succesfully !";
            
            
            return RedirectToAction("RoleIndex", "Account");
        }

This method takes "RoleName" as parameter and calls Roles.DeleteRole method to delete a role.

Note that there is no method in the Roles class called "EditRole" or "UpdateRole" so be careful while creating a new role and deleting a new role.


Assigning a Role to the User in ASP.NET MVC

Now, lets see how to assign a role to the user, to do that we have created a simple form that has a TextBox to accept username and a DropDown that lists all the roles from the database and it looks like below. In the same view, we have also created another form that accepts username and list all the roles associated with that username.

@{
    ViewBag.Title = "Role Add To User";
    Layout = "~/Views/Shared/_LayoutAdmin.cshtml";
}
<div class="spacerBody">
    <p>&nbsp;</p>
    @Html.ActionLink("Create New Role", "RoleCreate") | @Html.ActionLink("Roles", "RoleIndex")
        
<h2>Role Add to User</h2>

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

    <div class="message-success">@ViewBag.ResultMessage</div>
    <p>
        Username : @Html.TextBox("UserName")
        Role Name: @Html.DropDownList("RoleName", ViewBag.Roles as SelectList)
        
    </p>
    
    <input type="submit" value="Save" />
}



<div class="hr"></div>
@using(Html.BeginForm("GetRoles", "Account")){
    @Html.AntiForgeryToken()
    <p>Username : @Html.TextBox("UserName") 
        <input type="submit" value="Get Roles for this User" />
    </p>
}
       
@if(ViewBag.RolesForThisUser != null) {
    <text>
    <h3>Roles for this user </h3>
    <ol>
@foreach (string s in ViewBag.RolesForThisUser){
    <li>@s</li>   
}
                </ol>
    </text>
}
        </div>





The Controller code for this view page looks like below

        /// <summary>
        /// Create a new role to the user
        /// </summary>
        /// <returns></returns>
        [Authorize(Roles = "Admin")]
        public ActionResult RoleAddToUser()
        {
            SelectList list = new SelectList(Roles.GetAllRoles());
            ViewBag.Roles = list;

            return View();
        }

        /// <summary>
        /// Add role to the user
        /// </summary>
        /// <param name="RoleName"></param>
        /// <param name="UserName"></param>
        /// <returns></returns>
        [Authorize(Roles = "Admin")]
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult RoleAddToUser(string RoleName, string UserName)
        {

                if (Roles.IsUserInRole(UserName, RoleName))
                {
                    ViewBag.ResultMessage = "This user already has the role specified !";
                }
                else
                {
                    Roles.AddUserToRole(UserName, RoleName);
                    ViewBag.ResultMessage = "Username added to the role succesfully !";
                }
            
            SelectList list = new SelectList(Roles.GetAllRoles());
            ViewBag.Roles = list;
            return View();
        }

        /// <summary>
        /// Get all the roles for a particular user
        /// </summary>
        /// <param name="UserName"></param>
        /// <returns></returns>
        [Authorize(Roles = "Admin")]
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult GetRoles(string UserName)
        {
            if (!string.IsNullOrWhiteSpace(UserName))
            {
                ViewBag.RolesForThisUser = Roles.GetRolesForUser(UserName);
                SelectList list = new SelectList(Roles.GetAllRoles());
                ViewBag.Roles = list;
            }
            return View("RoleAddToUser");
        }

The first method of above code snippet simply gets all the roles from the database using "GetAllRoles()" method into SelectList and sets into the ViewBag.Roles. The same is being populated as DropDown into the view.

Clicking on Save method fires the 2nd method that first checks whether this user is already in the selected role, if not then calls "Roles.AddUserToRole" method to adds the username entered into textbox to associate with the role selected in the DropDown.

Listing Roles associated with a particular user in ASP.NET MVC
To list roles associated with a particular username, we have created another form in the same view that executes GetRoles method of the controller and calls "Roles.GetRolesForUser" method to get all roles associated with the username entered into the textbox. These roles are converted into SelectList and then set as "Roles into the ViewBag that ultimately renders the roles associated with a particular username.


How to remove a user from a role in ASP.NET MVC?

In order to remove a user from a particular role, I have again created a small form in the same above view (RoleAddToUser.cshtml) and here is the view code for this.

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

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

    <p>
        Username : @Html.TextBox("UserName")
        Role Name: @Html.DropDownList("RoleName", ViewBag.Roles as SelectList)
        
    </p>
    
    <input type="submit" value="Delete this user from Role" />
}
Writing the username in the TextBox, selecting a role from the DropDown and clicking Save button submit this form to the DeleteRoleForUser action method in the Account controller.



In the Account controller, my action method looks like this 

        [HttpPost]
        [Authorize(Roles = "Admin")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteRoleForUser(string UserName, string RoleName)
        {

                if (Roles.IsUserInRole(UserName, RoleName))
                {
                    Roles.RemoveUserFromRole(UserName, RoleName);
                    ViewBag.ResultMessage = "Role removed from this user successfully !";
                }
                else
                {
                    ViewBag.ResultMessage = "This user doesn't belong to selected role.";
                }
                ViewBag.RolesForThisUser = Roles.GetRolesForUser(UserName);
                SelectList list = new SelectList(Roles.GetAllRoles());
                ViewBag.Roles = list;
            

            return View("RoleAddToUser");
        }

In the above code snippet, I am checking whether the given username exists for that role or not, if yes then calling "Roles.RemoveUserFromRole" method. Following code is to write proper message and to make sure that the form is again getting loaded with the default data in the Role DropDown.


Checking for a particular role before performing any action in ASP.NET MVC

Now, there might be scenario where you need to check into the code block for a particular role for the  user before performing certain activity, to do that use below code

if (User.IsInRole("Admin"))
            {

                // Code to execute only when the logged in use is in "Admin" role

            }

The above code gets executed only when the logged in user belongs to "Admin" role.

Dig more methods of the "Roles" class and you will find many more interesting methods that helps you working with user roles in ASP.NET MVC.

Conclusion

Working with roles in ASP.NET MVC default project template is little tricky and this article explains that. Hope this article would be useful for people looking for working with Roles and managing roles in ASP.NET MVC.

Thanks for reading, do let us know your feedback and share this article to your friends and colleague if you liked. Do vote for this article.
Recommendation
Read Working with Roles in ASP.NET Identity for MVC after this article.
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
http://www.snarayan.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: Raja on: 11/10/2013 | Points: 25
Great job Sheo.

Very informative and simplified the complex stuff of ASP.NET that is hardly available on net.

Please keep writing.
Posted by: alex_fajardo2002-25286 on: 1/11/2014 | Points: 25
Good Day,

I have a bit of a problem in running this code, I've been banging my headboard for a couple of hours now but still can't get it to work. Here's the error :
Server Error in '/' Application.

Could not find stored procedure 'dbo.aspnet_CheckSchemaVersion'.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Data.SqlClient.SqlException: Could not find stored procedure 'dbo.aspnet_CheckSchemaVersion'.

Source Error:


Line 31: public ActionResult RoleIndex()
Line 32: {
Line 33: var roles = Roles.GetAllRoles();
Line 34: return View(roles);
Line 35: //return View();


Thank You,
Alex
Posted by: Sheonarayan on: 6/30/2014 | Points: 25
Hi Alex,

Looks like your database is not setup properly that is why the sp that should have been created automatically is not there or you might be choosing wrong version of roles provider and database.

I have never come across this error.

Sorry that you are getting this error.
Posted by: Hassaan on: 9/13/2014 | Points: 25
well im new to the asp.net MVC Simple membership

how a simple new user will enter the RolesCreate controller while the authorize attribute is for admin only ?

as per my understanding how admin authorise admin can allow new user with no role defined can enter it RolesCreate controller ?
Posted by: Sujaythedrummer on: 1/22/2015 | Points: 25
Thank you for the helpful post, although I am getting this error "There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'RoleName'." The error occurs in this line of code : Role Name: @Html.DropDownList("RoleName", ViewBag.Roles as SelectList. Could someone please share some light on this.
Posted by: Tbessi on: 2/11/2015 | Points: 25
Nothing happened:

Steps:
* Create MVC 4 Web Apps (With VS 2013 update 4)
- Create RoleCreate.cshtml under Views/Account
- Create RoleAddToUser.cshtml under Views/Account
- create RoleIndex.cshtml under View/Account

* Add your Authorization code under AccountController.cs ( public class AccountController : Controller)

When I run the Web Apps nothing happend even after login with admin user?

can you help with this situation
Posted by: Vin on: 8/23/2015 | Points: 25
is there anyway i can list all users? i want to show all users with or without roles so i can assign roles to those who doesnt have any
Posted by: Sheonarayan on: 4/12/2016 | Points: 25
@Vin,

Yes, there are ways to do this. You have context.Users collections, just use as if it is one of the entity collection.

If anyone is wondering what is "_LayoutAdmin.cshtml", it is just another layout page with admin related link so just copy-paste _Layout.cshtml page and rename it.

Thanks

Login to post response

Comment using Facebook(Author doesn't get notification)