Google

Asp.Net MemberShip with MVC4

Written on:October 10, 2012
Comments
Add One

MVC4 doesn’t use the same tables and infrastructure of MemberShip that Asp.Net or Asp.NET MVC3 used. You can see that just by creating a new MVC4 projet. You will notice that inside the Model folder that you have a class “AccountModel.cs”. Also, inside the AccountController.cs you will see the use of WebSecurity that come from WebMatrix namespace.

The default configuration ain’t a problem until you want to remove the DbContext from the Model folder (which shouldn’t be there but inside the DAL layer). Also, it’s ain’t a problem until you you like to auto generate the table inside the database with some data into it. Creating a user is pretty easy with WebSecurity but it’s not when you try to seed the database with it. In fact, you will get error message saying that WebSecurity need to be initialized before use and if you initialize it, the database might not be created by Entity Framework and then it crashes.

The solution is to use the Package Manager Console and to generate the database with some commands line. This processes is called “Migration”.

Removing default code

The first step is to clean up some code that doesn’t have its place. The first code to delete is inside AccountModels.cs inside the Models folder. You will see at the top of the file a class called UsersContext. This need to be removed.

The second code that need to be deleted is the filter InitializeSimpleMembershipAttribute. This filter create the tables for MemberShip if not created. Since we do not want to create on the fly but when the application start (or with commands line) we can delete this filter. It’s a good idea because it uses the UsersContext that we just deleted. This file is located inside the Filters folder.

The third code to remove is the filter use that is above the AccountController class inside AccountController.cs file.

Of course, now you have to setup your DbContext to be able to do what UsersContext was doing. If you compile now, it won’t compile because we have deleted the UsersContext. But, 2 lines of code is required inside AccountController.cs to be able to compile. The first one is to create in your DbContext a methbod to get the user by name and one to create a new user. Here is an example that use a “Service layer” to access the repository that will use a DbContext later.

Configure Entity Framework Migration

The next step is to make sure the the web.config contain the right provider for the role and membership. Inside web.config, in the system.web section be sure that you have the code below. If not, add it.

    <roleManager enabled="true" defaultProvider="SimpleRoleProvider">
      <providers>
        <clear/>
        <add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
      </providers>
    </roleManager>
    <membership defaultProvider="SimpleMembershipProvider">
      <providers>
        <clear/>
        <add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData"/>
      </providers>
    </membership>

This will specify that we are using the SimpleRoleProvider and the SimpleMembershipProvider. To be honest, I think with MVC4 it’s the default configuration so you do not required to do this but this website suggest to have it.

Once done, you need to build the Migration Configuration. This is automatically done if you are using the Package Manager Console. This tool can be open by going inside VIEW>Other Windows>Package Manager Console.

The next step is to use this command below that will force the creation of the configuration file. This will be required only once. Do not forget to use “EnableAutomaticMigration”. This will let you update the database later accordingly to changes you made to your model and entity configuration.

Enable-Migrations –EnableAutomaticMigrations -Force

Since we have removed the UsersContext we won’t have any conflict doing the command above. Otherwise, we would have need to specify which DbContext we want the migration to occur. Also, if you already had a database initializer (IDatabaseInitializer) like a “DropCreateDatabaseIfModelChanges”, this won’t work with the DbMigrationsConfiguration. In fact, you need to remove any initializer because we are switching to the Migration configuration. Nevertheless, this will give us additionnal control, more manual control but at least the possibility to generate the database automatically and also seed the database with Membership and custom tables.

The command creates a folder called Migrations with a Configuration.cs. Inside the Seed method, you will be able to create all data you want inside the database. Here is a small snippet of code that create a role, a user and some entities.

internal sealed class Configuration : DbMigrationsConfiguration<WorkoutPlanner.Database.DatabaseContext>
{
	public Configuration()
	{
		AutomaticMigrationsEnabled = true;
	}

	protected override void Seed(WorkoutPlanner.Database.DatabaseContext context)
	{
		base.Seed(context);

		WebSecurity.InitializeDatabaseConnection(
		"DefaultConnection",
		"UserProfile",
		"UserId",
		"UserName", autoCreateTables: true);

		if (!Roles.RoleExists("Administrator"))
			Roles.CreateRole("Administrator");

		if (!WebSecurity.UserExists("123123"))
			WebSecurity.CreateUserAndAccount("123123", "123123");

		if (!((IList<string>)Roles.GetRolesForUser("123123")).Contains("Administrator"))
			Roles.AddUsersToRoles(new[] { "123123" }, new[] { "Administrator" });

		context.Database.Initialize(true);
		context.Set<UserProfile>().Add(new UserProfile { UserId = 1, UserName = "123123" });
		
		context.Set<Workout>().Add(new Workout { Id = 1, Name = "My First workout user1", StartTime = DateTime.Now.Add(TimeSpan.FromDays(-10)), Goal = "Increase body mass" });
		context.Set<Workout>().Add(new Workout { Id = 2, Name = "My Second workout user1", StartTime = DateTime.Now, Goal = "Increase chest muscle, lower fat around abs" });
		
		
	}
}

The last step is to create table schema and insert those values from the seed configuration. This is done by this command :

update-database -verbose -force

The verbose will show you the SQL statement executed and the force will regenerate the table even if data already exist in those tables.

Conclusion

Any time you change your model or the configuration of your entities, you need to run update-database command. This will drop tables, create them again, create FK and insert seed data.

12 Comments add one

  1. I did almost the exact same things you did before finding your post.
    The initial organization of the UsersContext and filter seemed particularly strange to me.

    Glad to see I wasn’t the only one that thought so!
    Thanks for the detailed post on this.

  2. Thank you for your reply. This method work well but I have found that when the database is not present in the server that I need to execute twice in a row the update-database command. It seems that the database is not created and because of WebSecurity and the database context try to access it it crash. Executing twice the command solve the problem because the database exist the second time. Have you noticed this behavior?

  3. yahoo says:

    I and also my friends were actually analyzing the nice ideas located on your web blog and immediately came up with a terrible suspicion I had not expressed respect to the site owner for those tips. My people ended up for that reason glad to see them and already have very much been loving these things. Many thanks for simply being simply thoughtful as well as for settling on certain marvelous useful guides millions of individuals are really eager to be informed on. My personal sincere apologies for not expressing gratitude to sooner.

  4. Hey! I simply would like to give a huge thumbs up for the great info you’ve here on this post. I might be coming back to your blog for extra soon.

  5. Pingback:Custom MembershipProvider in MVC 4 | Code and Programming

  6. Christian says:

    When using CreateUserAndAccount, you should not create the User with “new UserProfile” as it creates both the user and account.

  7. Rrrr says:

    So, and what is _service variable on screenshot of accountcontroller.cs?

  8. pullareddy says:

    Thanks for your valuable post.it is very useful for me

  9. chandreshjulian says:

    _service giving an error: _service does not exist in current context

  10. picharnan says:

    Thank for your sharing. I’ll adapt your step with my project. MVC is easy step to code and design, MembershipProvide is easy to user management. :)

Leave a Comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>