Using SimpleMembership in ASP.NET MVC 4

Features such as membership and role management have been a part of ASP.NET core infrastructure since version 2.0. Developers have been using the default membership provider and role provider in their web applications. However, a common observation is that the default membership and role providers are quite rigid in terms of database schema and the way user information is stored. Luckily, SimpleMembership provides a helping hand in this area. It extends the core membership and role providers in such a way that you can use a custom database table to store user information. This article gives you step by step instructions to configure and use the SimpleMembership in ASP.NET MVC projects.

Overview of SimpleMembership

Authentication and authorization are commonly needed features in any modern web application. ASP.NET 2.0 introduced membership and role management through the provider model. Although the default membership and role providers work well in many situations, they are quite rigid in terms of database schema and the way they store user information in the database. For example, while using the default membership provider you don’t have much control on the table in which user names (login names) are stored. This rigidity creates difficulties in situations where user login information needs to be stored in a table with custom schema or in situations where authentication is happening via some third party (OAuth based authentication for example).

SimpleMembership, introduced with WebMatrix, tries to address these issues by offering a flexible model for authenticating the users. It relies on the core membership and roles provider of ASP.NET but wraps them in an easy to use and flexible way. Have a look at the following figure that shows the inheritance hierarchy of SimpleMembership.

The inheritance hierarchy of SimpleMembership

The inheritance hierarchy of SimpleMembership

WebMatrix.WebData assembly contains two important classes, viz. SimpleMembershipProvider and SimpleRoleProvider. The SimpleMembershipProvider class inherits from the ExtendedMembershipProvider class that in turn inherits from the MembershipProvider class residing in the System.Web.Security namespace. The SimpleRoleProvider class inherits directly from the RoleProvider class from the System.Web.Security namespace.

Obviously, in order to use SimpleMembership you must refer to the WebMatrix.WebData assembly in your ASP.NET MVC 4 project. If you create a new ASP.NET MVC project using the Internet Application template then by default the project template uses SimpleMembership and already refers to the WebMatrix.WebData assembly. The login system of this template is based on SimpleMembership. However, in the remainder of this article you will not use this template for a couple of reasons. Firstly, you may want to create a blank web site that doesn’t include SimpleMembership by default. Secondly, you may not want to use the default login system (AccountController) provided by the Internet Application template. In the later case it is important for you to understand how SimpleMembership works before you use it in your websites.

Creating a Database

For the sake of this example you will create a new SQL Server database named UserDb that stores user information. The following figure shows the Users table from the UserDb database:

The Users table from the UserDb database

The Users table from the UserDb database

As you can see, this is a custom table. SimpleMembership expects only two simple things from the table schema:

  • It should have a column that acts as a unique user identifier (Id column in this case).
  • It should have a column that acts as a login name (UserName in this case).

The interesting thing is that you can give any name to the above two columns. For example in the above figure the column storing user identifier is named as Id but you could have named it as UserID or Uid. Also, note that the Users table contains columns not used by SimpleMembership provider – DisplayName and Country. These columns are custom application specific columns and it depends on you as to how you would like to use the information stored in them.

Configuring an MVC Application to use SimpleMembership

In order to see how SimpleMembership can be used, create a new ASP.NET MVC 4 web application using the Empty project template and ASPX view engine.

New ASP.NET MVC 4 web application using the Empty project template and ASPX view engine

New ASP.NET MVC 4 web application using the Empty project template and ASPX view engine

Then add a reference to WebMatrix.WebData assembly using the “Add Reference” menu option. Merely adding a reference to WebMatrix.WebData is not sufficient. You also need to tell ASP.NET MVC to use this provider using the web.config file. So, open the web.config file and enable Forms authentication for your web application:

<authentication mode="Forms">
  <forms loginUrl="~/Account/Login" />
</authentication>

As shown above you set the authentication mode to Forms and also set the loginUrl to ~/Account/Login. You will develop the Account controller in later sections. Further add the following markup that specifies the provider information:

<membership defaultProvider="p1">
  <providers>
    <add name="p1" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData"/>
  </providers>
</membership>

<roleManager enabled="true" defaultProvider="p1">
  <providers>
    ...
  </providers>
</roleManager>

As you can see the <providers> section of the <membership> specifies the provider type as WebMatrix.WebData.SimpleMembershipProvider. Also, ensure that enabled attribute of <roleManager> is set to true to enable role management features.

Also, add a database connection string in the <connectionStrings> section that points to the UserDb database you created earlier.

<connectionStrings>
  <add name="UserDb" connectionString="data source=.\sqlexpress;
                     initial catalog=userdb;uid=<user_id_here>;pwd=<pwd_here>;
                     integrated security=sspi" providerName="System.Data.SqlClient" />
</connectionStrings>

Creating a User Registration Page

Next, add a new controller class to the project and name it as AccountController. The AccountController class contains all the action methods related to user registration, logging in and logging out. The following code shows the Register() action method that creates a new user.

[HttpGet]
public ActionResult Register()
{
    if (!WebSecurity.Initialized)
    {
        WebSecurity.InitializeDatabaseConnection("UserDb", "Users", "Id", "UserName", autoCreateTables: true);
    }
    return View();
}

[HttpPost]
public ActionResult Register(FormCollection form)
{
    WebSecurity.CreateUserAndAccount(form["username"], form["password"], new{DisplayName = form["displayname"], Country=form["country"]});
    Response.Redirect("~/account/login");
    return View();
}

The first version of the Register() action method is intended for GET requests (i.e. when user navigates to registration page) and accepts no parameter. This method invokes the InitializeDatabaseConnection() method of WebSecurity class. WebSecurity is a helper class and resides in WebMatrix.WebData namespace itself. The InitializeDatabaseConnection() method does an important task. It initializes a database and ensures that certain tables needed by SimpleMembership are available. The first parameter of the InitializeDatabaseConnection() method is the database connection string name as stored in the web.config file. The second parameter is the table name that stores user information. The third parameter is the name of the user identifier column. The fourth parameter is the name of the column that stores user names. The autoCreateTables parameter controls whether the tables needed by SimpleMembership are created automatically or not.

When the above call to the InitializeDatabaseConnection() method executes it creates the following tables in the UserDb database:

UserDb database

UserDb database

Notice all the tables that start with webpages_. They are needed by SimpleMembership to store membership and role information. Also notice that the call to InitializeDatabaseConnection() method is wrapped inside an if statement that checks whether the database is already initialized or not. This is done using the WebSecurity.Initialized property.

Now let’s discuss the second version of Register() action method. The second version is intended for POST requests and hence it accepts the FormCollection parameter. The Register view submits to this version of the Register() action method. Inside you use the CreateUserAndAccount() method of the WebSecurity class. The CreateUserAndAccount() method accepts UserName, Password and other pieces of information stored in the Users table. The properties of the anonymous object must match with the column names of the Users table. After successful registration the user is taken to the login page. The following figure shows the Register view:

The Register view

The Register view

Creating a Login Page

Now that you have completed the user registration page, let’s develop the login page and associated action methods. The following code shows Login() action methods from the AccountController:

[HttpGet]
public ActionResult Login()
{
    if (!WebSecurity.Initialized)
    {
        WebSecurity.InitializeDatabaseConnection("UserDb", "Users", "Id", "UserName", autoCreateTables: true);
    }
    return View();
}

[HttpPost]
public ActionResult Login(FormCollection form)
{
    bool success = WebSecurity.Login(form["username"], form["password"], false);
    if (success)
    {
        string returnUrl = Request.QueryString["ReturnUrl"];
        if (returnUrl == null)
        {
            Response.Redirect("~/home/index");
        }
        else
        {
            Response.Redirect(returnUrl);
        }
    }
    return View();
}

The first version of Login() action method is very similar to the first version of the Register() method and merely initializes the SimpleMembership. The second version of Login() action method is intended for POST requests. It gets called when the Login page is submitted by the end user. It accepts a parameter of type FormCollection. Inside, it calls the Login() method of WebSecurity by passing a user name and password. Recollect that you have enabled forms authentication for your web application and the last parameter of the Login() controls whether to create a persistent forms authentication cookie (true) or not (false). The Login() returns a boolean value indicating whether a login attempt was successful (true) or not (false). Based upon the outcome of the login process you can either take the user to another page or display some error message (not shown in the code above).

The Login view that submits to the Login() action method is shown below:

The Login view

The Login view

Individual action methods that expect a user to be authenticated can check whether a user has been successfully authenticated or not as follows:

public ActionResult Index()
{
    if (!WebSecurity.IsAuthenticated)
    {
        Response.Redirect("~/account/login");
    }
    return View();
}

The IsAuthenticated property of the WebSecurity class returns true if the current user is an authenticated user. If you wish you can also get the UserName using the CurrentUserName property of WebSecurity (not shown in the code).

Logging Out

Logging out a user is just a matter of calling the Logout() method of WebSecurity. The Logout() action method of the AccountController does just that and is shown below:

public ActionResult Logout()
{
    WebSecurity.Logout();
    Response.Redirect("~/account/login");
    return View();
}

Once a user is logged out he is taken back to the login page.

Role Management

You might be wondering how role management works under SimpleMembership. Since SimpleRoleProvider is directly based on the System.Web.Security.RoleProvider class, you can use the same core methods for role management. For example, you can use the Roles.CreateRole() method to create roles, Roles.GetAllRoles() to get a list of all the roles and so on. Though not discussed in this article, the WebSecurity class also adds a few easy to use methods that deal with authorization.

Summary

SimpleMembership provides a nice alternative to the default membership and role management features of ASP.NET. Built on the top of the core ASP.NET membership it allows you to have a custom database schema for the users table. The WebMatrix.WebData namespace includes SimpleMembershipProvider and SimpleRoleProvider classes that can be used as membership provider and role provider in an ASP.NET MVC application. The WebSecurity helper class is an easy to use wrapper that allows you to quickly authenticate a user.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read