Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a simple user roles - ASP.NET MVC C#

I'm pretty new to ASP.NET MVC, and I've been looking at a lot of different ways of adding User Roles for my ASP.NET MVC site. I want to use the users' database(s) that are automatically made for you when you make a new ASP.NET MVC project.

That contain the tables:

  • AspNetRoles
  • AspNetUserClaims
  • AspNetUserLogins
  • AspNetUserRoles
  • AspNetUsers

I've been looking at a few tutorials and it's a bit of a minefield for beginners I think.

All I want to be able to do is something like this:

[Authorize(Roles = "admin")]
public ActionResult Index()
{
    Return View();
}

So users with the role administrator can access the index page.

like image 268
Rob Avatar asked Feb 02 '15 16:02

Rob


1 Answers

The first step is to create the admin role. This is easy enough:

context.Roles.Add(new IdentityRole { Name = "admin" });
context.SaveChanges();

To add the role to an existing user:

var role = context.Roles.SingleOrDefault(m => m.Name == "admin");
user.Roles.Add(new IdentityUserRole { RoleId = role.Id });

Both of these steps can and should be handled in your Seed method of Migrations\Configuration.cs, along with creating any initial users that should be administrators.

For the ability of administrators to add roles to other users, you've got the first step covered already: protect the action with [Authorize(Roles = "admin")].

Next, you'll need a view model to work with your user. Something like the following:

public class UserViewModel
{
    // User properties you'd like to edit goes here

    public List<int> SelectedRoleIds { get; set; }

    public IEnumerable<SelectListItem> RoleChoices { get; set; }
}

You'll need to map your ApplicationUser to/from this view model. Then, you'll need to manually populate the two role properties in UserViewModel:

RoleChoices should be an enumerable of all available roles:

model.RoleChoices = context.Roles.Select(m => new SelectListItem
{
    Value = m.Id,
    Text = m.Name
});

SelectedRoleIds should be a list of the ids of all roles currently assigned to the user:

model.SelectedRoleIds = user.Roles.Select(m => m.RoleId);

In your view, then, you'll construct your multiselect:

@Html.ListBoxFor(m => m.SelectedRoleIds, Model.RoleChoices)

When creating a new user, you can simply set the user's roles directly on post:

user.Roles = model.SelectedRoleIds.Select(m => new IdentityUserRole { RoleId = m });

When editing an existing user, greater care has to be taken, since you'll get integrity errors if you save the same role id twice for the same user. First, you'll need to remove any roles that have been deselected:

user.Roles.Where(m => !model.SelectedRoleIds.Contains(m.RoleId))
    .ToList().ForEach(role => user.Roles.Remove(role));

Then, you'll need to add any newly selected roles:

var existingUserRoles = user.Roles.Select(m => m.RoleId);
model.SelectedRoleIds.Except(existingUserRoles)
    .ToList().ForEach(roleId => user.Roles.Add(new IdentityUserRole
    {
        RoleId = roleId
    }));
like image 193
Chris Pratt Avatar answered Sep 19 '22 20:09

Chris Pratt