Seeding Membership & Roles in ASP.NET MVC 4

Wednesday, September 5, 2012

Jon Galloway has an overview of the new membership features in ASP.NET MVC 4. The Internet project template moves away from the core membership providers of ASP.NET and into the world of SimpleMembershipProvider and OAuth.

There is quite a bit I could write about the new features and the code generated by the Internet project template, but for this post I just want to cover a scenario I've demonstrated in the past - seeding the roles and membership tables. If you are using Entity Framework code-first migrations it's relatively easy to add some code to the Seed method of the migrations configuration to populate the membership tables with some initial roles and users. Just remember every update-database command will call the Seed method, so you have to write the code to make sure you don't try to create duplicate data.

First, the new project template creates an MVC 4 Internet application without any provider configuration, but for the membership features to work properly during a migration, it appears you need at least some configuration. The following code makes sure the SimpleMembershipProvider and SimpleRolesProvider are in place.

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

Then inside the Seed method of the DbMigrationsConfiguration<T> derived class, you can have:

protected override void Seed(MovieDb context)
{
//context.Movies.AddOrUpdate(...);

// ...

SeedMembership();
}

private void SeedMembership()
{
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("sallen",false) == null)
{
membership.CreateUserAndAccount("sallen", "imalittleteapot");
}
if (!roles.GetRolesForUser("sallen").Contains("Admin"))
{
roles.AddUsersToRoles(new[] {"sallen"}, new[] {"admin"});
}
}

Comments
Guillaume Wednesday, September 5, 2012
This is nice and simple, but to do that in my DTO assembly, I need to add a few Web references.
Why is this security stuff so linked to Web ?
gravatar scott Wednesday, September 5, 2012
All these WebMatrix-y pieces are, unfortunately, tightly bound to the web. In fact, it's not hard to create exceptions when you use the bits outside an HTTP request. Exceptions like "must be initialized before App Start", and other rubbish, which is unfortunate. I could write an entire article on the weirdness I've seen.
gravatar Osman Celik Thursday, September 6, 2012
Man you are the Savior! I was wondering why I m getting exception of WebSecurity and _appStart.chtml . Could you writeabout this much and much more may be a pluralsight series. New Membership features really confusing coz vs2012 beta and RTM default mvc templates are quite different.
gravatar Osman Celik Thursday, September 6, 2012
And also it works with local db but not sqlexpress. Its giving System.Web.Security.MembershipCreateUserException: The Provider encountered an unknown error? Any idea?
gravatar scott Thursday, September 6, 2012
@Osman - will try it out, but will need a few days first.
gravatar Osman Celik Thursday, September 6, 2012
Sure man.
There is lack of documentation. it seems mvc uses localdb, code migration and every stuff working properly, but chaging the connection string to any sqlserver or sqlexpress almost breaks everything. I think there has to be some sort of webconfig element to change it to sql to make it work properly. So take your time and if you can do a comprehensive work on new membership stuff would be awesome. And getting webmatrix-s exception error messages in the mvc project makes me laugh, and its really confusing. For the first time when I get InitializeDatabase exception with _appStart.cshtml error message, I look in the project find that file. Its too funny I know but it was the message. No doc, no info, nothing. MVC4 membership is a mess and damn confusing. By the way i m using msdn copy of ultimate version. Thanks!
gravatar Riderman Friday, September 7, 2012
he following error occurs after running the method Seed:

No user table found that has the name "Usuario".

My Configuration class:

protected override void Seed(CreditoImobiliarioContext context)
{
base.Seed(context);

WebSecurity.InitializeDatabaseConnection("Data","SimpleProvider", "Usuario", "Id", "Email", false);
if (!WebSecurity.UserExists("ridermansb@bindsolution.com"))
WebSecurity.CreateUserAndAccount("ridermansb@bindsolution.com", "123456", new { Nome="Riderman de Sousa Barbosa" });

}
gravatar sebastian Monday, September 10, 2012
Hi Scott, refering to simplemembership, do you know if its possible to extend it using open source http://aspnetwebstack.codeplex.com/ in order to be able to allow anonymous users? I checked the msdn.microsoft.com/...(v=vs.111) simplemembership provider class but its methods have no reference to anonymous identifications.
brgds!
gravatar scott Tuesday, September 11, 2012
@sebastian: simple membership is limited, you might try building on the ExtendedMembershipProvider that the simple provider uses behind the scenes.

@riderman: did you already have the table created?

@osman: still haven't had a chance yet. feel free to email me directly.
larry Thursday, September 13, 2012
My EF context lives in a separate project in my solution from my MVC4 app. Is there any way to get the EF Seed method to have access to the Role/Membership providers in this case?
gravatar scott Thursday, September 13, 2012
@larry - yes, you'll need to reference the right assemblies - System.Web and WebMatrix.Data.
gravatar Онлайн игры для детей Thursday, September 27, 2012
Thenks! I found lots of interesting information here.
gravatar Dave Thursday, September 27, 2012
Scott, really hoping you can help as I'm at my wits end on this one. I create an MVC4 internet application, add my sql database using ado.net EF, change connection strings for SimpleMembership (in InitializeSimpleMembershipAttribute.cs and AccountModel.cs), run the app and hit error on LazyInitializer.EnsureInitialized method. Looked everywhere on the net! Went through courses on PluralSite, nothing that works!How do I get this working? thx
gravatar Jose Luis Sunday, September 30, 2012
Hello how to work with a connection that sus EF model first provider = "...EntityClient" ?

Tx
gravatar scott Monday, October 1, 2012
@Jose: Migrations only works with DbContext, as far as a I know.

@Dave: what is the error message?
gravatar Ren&#233; Johnsen Friday, October 5, 2012
Hi Scott,

Any chances that you would update your Pluralsight video ASP.NET MVC 4 Fundamentals part two on authorization and security to reflect the fact that the default config is now oauth? I'm an ASP.NET MVC rookie, and I got stuck when you started the authorization stuff. My web.config has a lot of oauth, but no membership tags..
Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!