The MVC4 Internet template assumes that it will be adding a user table called “UserProfile” to your database. What I think a high percentage of developers would want is to use their domain model’s “user” entity and have SimpleMembership just manage the passwords. In this blog post I will demonstrate how I did this and welcome alternative suggestions.
I recommend you first understand the authentication process provided by the MVC 4 Internet template. There are 2 fantastic posts you should read first.
- MVC 4 Authentication
- SimpleMembership, Membership Providers, Universal Providers and the new ASP.NET 4.5 Web Forms and ASP.NET MVC 4 templates
In addition, please check out Scott Allen’s excellent Pluralsight course called “Building Applications with ASP.NET MVC 4”.
MVC 4 Internet Template with pre-existing Domain Model
Create a new ASP.NET MVC 4 Internet Application and name it “SimpleMemberExample”
Custom Domain Model/Database
The first thing I want to do is create the custom domain model/database. In the “Model” directory, lets add a class that represents our custom “User” table. Lets call this custom user entity “Administrator” as seen here:
namespace SimpleMembershipExample.Models { public class Administrator { public Administrator(){} #region Fields and Properties public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } #endregion } }
(I was unable to figure out how my user table’s unique identifier could use a Guid. I think the unique identifier of your custom user entity/table must be an int to use SimpleMembership. anyone know?)
Lets add a custom DbContext as shown here to the root of the project.
using System.Data.Entity; using SimpleMembershipExample.Models; namespace SimpleMembershipExample { public class SomeAppDbContext: DbContext { public SomeAppDbContext(): base(nameOrConnectionString: "SomeAppName"){} public DbSet<Administrator> Administrators { get; set; } } }
The DbContext only contains a single table called Administrators just to keep this super duper easy. Yours would contain lots more. Notice in the custom constructor, I am telling the DbContext to use a specific connection string. Lets add that connection string to the Web.Config.
This connection string could be anything you want it to be.
Just for demo purposes, I am naming the database “SomeAppName”. As a final step, in “Global.asax.cs”, put the following code:
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { SomeAppDbContext dbcontext = new SomeAppDbContext(); dbcontext.Administrators.All(i => i.Name != "Dan");
Running the application, the magical EF Code First will create the following database. We have a custom database with a custom user table called “Administrators”.
Customizing MVC 4 Internet Template
Remove InitializeSimpleMembershipAttribute
The Internet template contains an Action filter called “InitializeSimpleMembershipAttribute”. I deleted that class and removed any references to it.
Replace UserProfile with your Custom User Entity
The Internet template assumes that it will be adding a user table called “UserProfile” to your database. What I think a high percentage of developers would want is to use their domain model’s “user” entity and have SimpleMembership just manage the passwords. Let me demonstrate how to do this.
In the “Model” folder, in the “AccountModel.cs” file, delete the “UserProfile” class. We want to use our “Administrator” entity instead. Wherever UserProfile is referenced elsewhere, replace with Administrator. The original UserProfile had properties called “UserName” and “UserId”. Administrator has properties “Name” and “Id”. Make sure to sync those properties up.
I want to have only 1 DbContext and I want to use my DbContext. In the “Model” folder, in the “AccountModel.cs” file, delete the “UsersContext” class. Wherever UsersContext is referenced elsewhere, replace with SomeAppDbContext.
Call WebSecurity.InitializeDatabaseConnection
As a final step, in “Global.asax.cs”, put the following code:
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { SomeAppDbContext dbcontext = new SomeAppDbContext(); dbcontext.Administrators.All(i => i.Name != "Dan"); WebSecurity.InitializeDatabaseConnection("SomeAppName", "Administrators", "Id", "Name", autoCreateTables: true);
WebSecurity.InitializeDatabaseConnection takes the web.config connection string name, the name of your custom user table (“Administrators”), the unique identifier field name of your user table (“Id”) and the user name field. Running the InitializeDatabaseConnection method does several things:
- Initializes the static Roles and WebSecurity classes.
- Adds the following tables to your database: webpages_Membership, webpages_OAuthMembership, webpages_Roles, webpages_UsersInRoles, UserProfile.
Running the Internet Application
When you run the code with those changes, the following database is created:
The home screen looks like this:
Click on the Register link in the upper right.
Fill out the form and click the “Register” button. The MVC 4 Internet template application will navigate you back to the home page.
Notice it knows the name you registered with. If you check for cookies, you will see the typical ASPXAUTH as shown below.
If you click the “Log off” link and check cookies, the ASPXAUTH cookie disappears. The ASPXAUTH cookie is the key to the authentication.
When you look at the database you will see the following:
Notice with the code changes, the MVC Internet template knew to save to the custom user table “Administrators”. The password was saved to the webpages_Membership table with a foreign key relationship to the Administrators table.
Please download the code here.
