SimpleMembership with an existing database.

I’ve been trying the SimpleMembership today and I just love it, the Asp.Net team came out with the simplest solution, great!

Managing users and their rights has always been a pain using the built in Membership feature pushing many developer to write their custom user/role tables, spending a lot of time in configuration and extending the various MembershipProvider and RoleProvider, as I did. SimpleMembership addresses that, but let’s start from the beginning, it will be quick don’t worry!

Authorization vs Authentication

The Asp.Net membership provides a  built in solution to manage authentication and authorization. While the Authentication defines the mechanism used to assign an identity (and eventually one or more roles) to a user, the authorization simply defines what an user or a role can access. The definition is obvious but necessary, because one of the main criticism is that in order to get even a basic authentication in place  there’s a lot of  setup code, including  functionality that will be hardly used. So basically in order to get to this:

if(User.Identity.IsAuthenticated && User.IsInRole("Administrator"))
{
 //do something
}

You need this (see picture below) and yes, it comes with a lot of lovely keys required in the web.config. It’s a bit too much for getting to the point to where I can safely assign a forms authentication ticket (ASPXAUTH cookie) to my user.Details on how to create the database can be found here.

membership schema

Universal Providers

Things improved with the recent introduction of the Universal Providers. Enabling support for all the SQL Server family, including azure, they can be easily integrated with the new DotNetOpenAuth providers and give back a cleaner database (picture below).  The main bits however remains the same: config keys needed for roles/profiles/membership, which is fine if you want to tune the default behaviour!

SimpleMembership

And what if instead you’re happy with that default behaviour and you want to get immediately productive, skipping all the configuration part ? SimpleMembership is the answer.

A new security provider actually hosted in the WebMatrix.WebData.dll and added by default within the Website template in Visual Studio, reducing to the essential both the SQL dependencies and the code to implement to get it working.  John Galloway gives a great overview of the SimpleMembership class in his post, describing how it inherit from ExtendedMembershipProvider, which extends the classic MembershipProvider.

All this goodness is accessed within webpages/controllers through the static WebSecurity class, which embeds all the authentication features usually needed, including the FormsAutentication SignIn/SignOut. For instance with a call to WebSecurity.Login a user get both validated and receive the authentication cookie I was talking about previously.All without one line of config. That’s awesome.
websecurityclass login

The database produced is really tiny and the required tables can be easily included within an existing one, using EFCode first for instance.

How does it works ? The SimpleMembership in order to work with your existing user table need a UserId and a UserName columns.  These values will then been used internally by the provider to hook up with the other membership tables containing the remaining bits that compose the full user profile. You can add the columns to any table as long it is decorated with the UserProfile attribute.

[Table("UserProfile")]
public class UserProfile
{
 [Key]
 [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
 public int UserId { get; set; }
 public string UserName { get; set; }
 public string Email { get; set; }
}

That’s it. UserProfile can be any of the tables of my current EFContext, just comment out the default connection string for the application services database on the web.config and use the DataContext one when initialiting the Membership. By default. with the MVC project, the membership get initialized within the AccountController with the [InitializeSimpleMembership] attribute, let’s comment it out and move the WebSecurity.InitializeDatabaseConnection  call in the global.asax.

protected void Application_Start()
{
 AreaRegistration.RegisterAllAreas();
 WebApiConfig.Register(GlobalConfiguration.Configuration);
 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
 RouteConfig.RegisterRoutes(RouteTable.Routes);
 BundleConfig.RegisterBundles(BundleTable.Bundles);
 AuthConfig.RegisterAuth();

//initialiting the database
 Database.SetInitializer(new DataContextInitializer());
 DataContext c = new DataContext();
 c.Database.Initialize(true);
 //DefaultConnection is used by the EF Context too.
 WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName",
 autoCreateTables: false);
}

Now that all is place, an example of why WebSecurity make it easy is the method CreateUserAndAccount. The result is the creation of a user record for our entity table plus its membership account. Note that the Email field is a custom column and it can be easily passed with an anonymous type to the method.

WebSecurity.CreateUserAndAccount("xyzUser", "xyzPassword", new { Email = "xyzUser@mail.com" }, false);

simplemembershiprecord

That’s basically all it takes to get started with the SimpleMembership. Despite a lack of documentation here are some useful links:

Most of the answers can also be found by simply investigating the WebMatrix.WebData assembly with ILSpy !

MVC Radiobutton group

In order to group a series of radiobutton and allow only one control of the group to be selectable we’ll have to set the same value for the “name” attribute on all controls of the group. In Vb.Net

Code Snippet
<div id="group1">
    @Html.RadioButton("group1", False, New With {.class = "radioClass"})
    @Html.RadioButton("group1", False, New With {.class = "radioClass"})
    @Html.RadioButton("group1", False, New With {.class = "radioClass"})
</div>
<div id="group2">
    @Html.RadioButton("group2", False, New With {.class = "radioClass"})    
    @Html.RadioButton("group2", False, New With {.class = "radioClass"})
    @Html.RadioButton("group2", False, New With {.class = "radioClass"})
</div>

From Asp.net Webforms to Asp.net MVC

I’ve been using MVC recently for a while now, both at work and on my own, I am really enjoying it, the implementation proposed by Microsoft is simple and effective and it sticks more to the nature of a web session(request/response) than the Webform model with all it’s page lifecycle, control events and so on.  The move to MVC should happen when you are not using anymore the core feature of Asp.net Webforms: its controls. If you find yourself creating an html list inside the aspx page using a foreach instead of using a repeater, if you prefer using jQuery instead of an Update Panel, then you should move to MVC.

This is not a comparison between the two tecnologies, there’s plenty of resources out there, here are the key points making me prefer MVC over Webforms.

  • Absence of  in-between page states (Page load, render etc),  with MVC you call an action and you get a response back, that’s it.
  • Cleaner pages without generated code (es ViewState).
  • More control over the content and what is rendered using a View engine and html instead of webcontrols.
  • Possibility to unit test each request a client will make.
  • A lot of community resources.

Webforms has been the perfect fit in the pre Ajax era, when tools like jQuery didn’t exist, the common focus was on trying to do everything “server side”. MVC reverse this statement: the look and behaviour of the page is handled by the View while the server is only responsible of receiving and responding to the client requests. Assuming that with both MVC and Webforms you can achieve exactly the same goals, the choice is really up to how many feauters of each model you will use.