How exactly to use roles in Asp.NET MVC 4?

I read a lot of articles and forums, but I still canโ€™t figure it out ... I am creating an Internet application using Visual Studio Express 2012 for the Internet, with MVC4 + Razor + Entity Framework CodeFirst.

As I understand it, managing users and roles in MVC4 using SimpleMembership is more straightforward than in previous versions, and should be fairly simple.

In my application, I need to authorize only certain user groups (for example, only admins can access certain pages). I understand that this is done by passing the parameter to the annotation [Authorize]: [Authorize (Roles = "Admins")] But how do I create these roles and how to add users to them?

To require authentication, I added the [Authorize] annotation (without parameters) on top of the controller method, and it worked without any additional configurations or adding anything else. Also, when I look at the database that was automatically created, I see a table called webpages_UsersInRoles, with UserId and RoleId columns. All this makes me think that this should be a fairly simple task, since everything seems configured and ready to use, but I just can not figure out how;)

What I tried so far (and this did not work) was as follows: I have a DataContextDbInitializer class that inherits from DropCreateDatabaseIfModelChanges. The Seed method is overridden inside this class, and I added this (I had to import System.Web.Security):

Membership.CreateUser("user1", "123456"); Roles.CreateRole("Admins"); Roles.AddUserToRole("user1", "Admins"); 

I also added this tag to the tag of the Web.config file:

 <roleManager enabled="true" cacheRolesInCookie="true" > </roleManager> 

To try, I added [Authorize (Roles = "Admins")] on top of the action method in the controller, and then logged in as "admin" and tried to access this method, but no luck :(

I donโ€™t know what else Iโ€™m missing ... I would be very happy if someone could direct me to this, since it was driving me crazy: P

Thanks!

+4
source share
2 answers

I assume your Seed method is not called. Make sure this is called by setting a breakpoint in the method and running it in the debugger. Unless you made some other changes to your application, EF migration is not used. By default, the database is initialized using InitializeSimpleMembershipAttribute . You will see that this attribute is added to the Account Controller, as shown in the following code.

 [Authorize] [InitializeSimpleMembership] public class AccountController : Controller { .... } 

Thus, it is called only when AccountController is accessed. You will find the definition in Filters \ InitializeSimpleMembershipAttribute.cs. Here is a snippet of code from this class, which may be the key to why it is not being called.

 // Create the SimpleMembership database without Entity Framework migration schema ((IObjectContextAdapter)context).ObjectContext.CreateDatabase(); 

The InitializeSimpleMembershipAttribute code contains a lot of code for processing the script when forms authentication is not used for the MVC application. If you always use Authentication Forms, you can exclude this code and initialize the database yourself. Just remove this attribute from the AccountController and put your own initialization code in the Global.asax Application_Start method. You would add something like this to the Application_Start method

 Database.SetInitializer<UsersContext>(new MyDBInitializer()); 

Seed method is as follows

 WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true); var roles = (SimpleRoleProvider)Roles.Provider; var membership = (SimpleMembershipProvider)Membership.Provider; if (!roles.RoleExists("Admin")) { roles.CreateRole("Admin"); } if (membership.GetUser("user1", false) == null) { membership.CreateUserAndAccount("user1", "123456"); } if (!roles.GetRolesForUser("user1").Contains("Admin")) { roles.AddUsersToRoles(new[] { "user1" }, new[] { "Admin" }); } 

Note that you need to initialize the web matrix security database in Seed by calling the WebSecurity.InitializeDatabaseConnection method.

You can find more information about visiting SimpleMembership in this blog post , which includes the full source code for the sample project.

+6
source

Finally, I managed to work it all out!

My seed method now looks like this:

 WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true); if (!Roles.RoleExists("Admins")) { Roles.CreateRole("Admins"); } if (!WebSecurity.UserExists("admin")) { WebSecurity.CreateUserAndAccount("admin", "123456"); } if (!Roles.GetRolesForUser("admin").Contains("Admins")) { Roles.AddUsersToRoles(new[] { "admin" }, new[] { "Admins" }); } base.Seed(context); 

My App_Start in Global.asax looks like this:

 Database.SetInitializer(new DataContextDbInitializer()); DataContext c = new DataContext(); c.Database.Initialize(true); 

I'm not sure if this really does something, but I have this inside the system.web tag in Web.config:

 <roleManager enabled="true" cacheRolesInCookie="true" /> 

I also removed [InitializeSimpleMembership] from AccountController and the UsersContext class in AccountModels. I have moved this bit to my own context class:

 public DbSet<UserProfile> UserProfiles { get; set; } 

Then, to check if everything works, I use the [Authorize (Roles = "Admins")] annotation on top of the About () method in the HomeController. If everything works as expected, this should force me to log in as admin / 123456 to be able to see the "O" page controlled by HomeController / About. What is he doing;)

+3
source

All Articles