Seed Users and Roles with MVC 4, SimpleMembershipProvider, SimpleRoleProvider, Entity Framework 5 CodeFirst, and Custom User Properties

I’ve been Googling over the weekend and so far didn’t find any articles out there on how integrate EF5 CodeFirst nicely with SimpleMembership and at the same time, seeding some of your users, roles and associating users to roles while supporting custom fields/properties during registration, hence this blog post.

I think this is a nice to have, especially during PoC development where you could be developing features that depend on authentication and authorization while making schema changes with EF CodeFirst. The last thing you want to do is run update-database for migrations and have to manually re-insert/re-seed all your users, roles and associating the two every time you ran migrations (e.g. update-database -force from the Package Manager Console).

First, create an “Internet Application” ASP.NET MVC4 Project, because this is the only out of the box MVC template that has the new SimpleMembershipProvider wired up out of the box. One of the features I like the most about the SimpleMembershipProvider is it gives you total control of the highly requested “User” table/entity. Meaning you integrate SimpleMembershipProvider with your own user table, as long as it has a UserId and UserName fields in your table.

Obviously there are many more features in SimpleMembership provider, here are some links in this regard:

Explicitly wire up the providers even though this is implied, so that when do run the “update-database” command from the Package Manager Console for migrations we can use the native “Roles” Api.

In the “System.Web” Section add:


    <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>

Let’s add a custom field to the User table by adding a Mobile property to the UserProfile entity (MVC4SimpleMembershipCodeFirstSeedingEF5/Models/AccountModel.cs).


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

Enable EF5 CodeFirst Migrations

Seed your Roles and any Users you want to provision, also note the WebSecurity.InitializeDatabaseConnection method we are invoking. This method is what tells SimpleMembership which table to use when working with Users and which columns are for the UserId and UserName. I’m also going to demonstrate how you can hydrate additional custom columns such as requiring a User’s mobile number when registering on the site.


#region

using System.Data.Entity.Migrations;
using System.Linq;
using System.Web.Security;
using MVC4SimpleMembershipCodeFirstSeedingEF5.Models;
using WebMatrix.WebData;

#endregion

namespace MVC4SimpleMembershipCodeFirstSeedingEF5.Migrations
{
    internal sealed class Configuration : DbMigrationsConfiguration<UsersContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
        }

        protected override void Seed(UsersContext context)
        {
            WebSecurity.InitializeDatabaseConnection(
                "DefaultConnection",
                "UserProfile",
                "UserId",
                "UserName", autoCreateTables: true);

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

            if (!WebSecurity.UserExists("lelong37"))
                WebSecurity.CreateUserAndAccount(
                    "lelong37",
                    "password",
                    new {Mobile = "+19725000000"});

            if (!Roles.GetRolesForUser("lelong37").Contains("Administrator"))
                Roles.AddUsersToRoles(new[] {"lelong37"}, new[] {"Administrator"});
        }
    }
}

Now, run the update-database -verbose command from Package Manager Console, we are using the -verbose switch so that we can get better visibility on what’s getting executed on SQL. Notice the Mobile field is being created.

Let’s go ahead and do a sanity check and make sure all of our Users and Roles were provisioned correctly from the Seed method in our migration configuration, by executing a few queries.


SELECT TOP 1000 [UserId]
      ,[UserName]
      ,[Mobile]
  FROM [aspnet-MVC4SimpleMembershipCodeFirstSeedingEF5].[dbo].[UserProfile]
  
  SELECT TOP 1000 [RoleId]
      ,[RoleName]
  FROM [aspnet-MVC4SimpleMembershipCodeFirstSeedingEF5].[dbo].[webpages_Roles]
  
  SELECT TOP 1000 [UserId]
      ,[RoleId]
  FROM [aspnet-MVC4SimpleMembershipCodeFirstSeedingEF5].[dbo].[webpages_UsersInRoles]

Results

  • Users were inserted
  • Roles were provisioned
  • The user “LeLong37″ was added and associated to the Administrator role

Finally for a sanity check, let’s go ahead and run the app and sign-in with the provisioned user from our Seed method.

Successfully authenticated with our seeded provisioned user (thought I’d add a blue star badge to the screenshot to add some humor :P )!

One last thing, let’s go ahead and modify our Register view, Register model and AccountController to gather the user’s mobile number during registration.

Register View (Register.cshtml)


@model MVC4SimpleMembershipCodeFirstSeedingEF5.Models.RegisterModel
@{
    ViewBag.Title = "Register";
}

<hgroup class="title">
    <h1>@ViewBag.Title.</h1>
    <h2>Create a new account.</h2>
</hgroup>

@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    <fieldset>
        <legend>Registration Form</legend>
        <ol>
            <li>
                @Html.LabelFor(m => m.UserName)
                @Html.TextBoxFor(m => m.UserName)
            </li>
            <li>
                @Html.LabelFor(m => m.Password)
                @Html.PasswordFor(m => m.Password)
            </li>
            <li>
                @Html.LabelFor(m => m.ConfirmPassword)
                @Html.PasswordFor(m => m.ConfirmPassword)
            </li>
            <li>
                @Html.LabelFor(m => m.Mobile)
                @Html.TextBoxFor(m => m.Mobile)
            </li>
        </ol>
        <input type="submit" value="Register" />
    </fieldset>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}


Register model (AccountModel.cs)


    public class RegisterModel
    {
        [Required]
        [Display(Name = "User name")]
        public string UserName { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }

        [Required]
        [DataType(DataType.PhoneNumber)]
        [Display(Name = "Mobile")]
        public string Mobile { get; set; }
    }


Register Action (AccountController.cs)


        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {
                    WebSecurity.CreateUserAndAccount(
                        model.UserName, 
                        model.Password, 
                        new { Mobile = model.Mobile }, 
                        false);

                    WebSecurity.Login(model.UserName, model.Password);
                    return RedirectToAction("Index", "Home");
                }
                catch (MembershipCreateUserException e)
                {
                    ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

Finally, let’s register.

Let’s go ahead and run our SQL queries again and make sure the mobile number was actually saved to our UserProfile table during the registration.

Sweet! Registration successful, with mobile number saved to the UserProfile table.

Happy Coding…!

Download Sample Application: http://blog.longle.net/2012/09/26/multi-step-asp-net-mvc-4-registration-with-sms-using-twilio-cloud-communication-and-simplemembershipprovider-for-increased-user-validity/

About these ads

171 thoughts on “Seed Users and Roles with MVC 4, SimpleMembershipProvider, SimpleRoleProvider, Entity Framework 5 CodeFirst, and Custom User Properties

  1. Do you have a spam problem on this website;
    I also am a blogger, and I was wanting to know your situation; we have created some
    nice methods and we are looking to trade strategies with others, be sure to shoot me an email if interested.

  2. Pingback: [RESOLVED]Asp.net Membership and Entity Framework | ASP Web Form Data Control

  3. Pingback: [RESOLVED]Asp.net Membership and Entity Framework | ASP Questions & Answers

  4. I have been surfing online more than 3 hours today, yet I never
    found any interesting article like yours. It is pretty worth enough for me.
    Personally, if all site owners and bloggers made good content as you did,
    the net will be much more useful than ever before.

  5. It’s a shame you don’t have a donate button! I’d without a doubt donate to this fantastic blog!

    I suppose for now i’ll settle for book-marking and adding your RSS feed to my Google account.
    I look forward to brand new updates and will share this website with my Facebook group.

    Chat soon!

  6. When i run the update command it gives me an error ‘Invalid Column Name Mobile ‘
    Help Me i am stuck . thanks in advance

  7. Excellent items from you, man. I have keep in mind your stuff
    previous to and you’re just too great. I actually like what you’ve bought here, really like
    what you’re saying and the way wherein you assert it.
    You are making it enjoyable and you still care for to keep it sensible.
    I cant wait to learn much more from you. This is actually a wonderful website.

  8. I don’t even know how I ended up here, but I thought this post was good.

    I do not know who you are but certainly you are going to a famous blogger if you are not
    already ;) Cheers!

  9. What does it mean “Seed your Roles and any Users you want to provision, also note the WebSecurity.InitializeDatabaseConnection method we are invoking.”?

    I have no idea what you mean. Also, where does the code below that line go? New file?

  10. I get an error when I followed ur tutorial: Cannot attach the file ‘C:.…\MvcApplication7\MvcApplication7\App_Data\MvcApplication7′ as database ‘MvcApplication7′. Is it because I moved public DbSet UserProfiles { get; set; } to my own Contextclass? I want to add some more DbSets.

  11. Pingback: Good To Know: ASP .NET MVC Reference Guide | For the love of problems :)

  12. Thanks a bunch for sharing this with all of us you really
    realize what you are talking approximately! Bookmarked.
    Please also consult with my website =). We may have a hyperlink exchange agreement
    among us

  13. Read on for little ways to save money, aand see
    how your efforts caan really add upp over time. >>Here you juust
    need to duscuss yyour preferences annd design of the cards.
    It is not prwctical to find families that don’t have an idea about
    this wonderful soft drink that works just like soda.

  14. Thanks what a great post! Worked a treat, except I had to add the following to the “system.web” section of my app’s web.config:

    	<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>
    

    Hope this helps someone else in future…!

  15. Thank you very very Much!!! I wish more people would put out easy to comprehend information like this piece. So many of us try to answer with incomplete articles or comments with little how to detail information. Everyone should remember it someone is looking for and answer then they don’t know. :-) Once again fantastic piece keep it up. Helped me gain a day of work back. I hope to be able to return the favor some day.

    Cheers!

  16. I changed my UserProfile table from userID to userGUID

    Getting this error.
    Cannot convert type ‘System.Guid’ to ‘int’

  17. Pingback: Redundant explicit property name in C# warning - C# Questions Solutions - Developers Q & A

  18. Pingback: H-Li | ASP.NET MVC 4使用技巧记录2: 如何进行Migrations和使用Simplemembership

  19. Hello, I think your blog might be having browser compatibility issues.
    When I look at your blog site in Ie, it looks fine but when opening in Internet Explorer, it has some overlapping.
    I just wanted to give you a quick heads up! Other then that,
    wonderful blog!

  20. Hi

    Thanks for the blog. Can you please tell how can I display a user’s first name instead of the username in the logged in view?

  21. Undeniably believe that which you said. Your favorite justification seemed to be on the net
    the easiest thing to be aware of. I say to you, I definitely get annoyed while people consider worries
    that they just do not know about. You managed to hit the nail upon the top and also defined out the whole thing without having side-effects
    , people could take a signal. Will likely be back to get more.
    Thanks

  22. Is it the file starting ‘building a composite mvc3….’?

    That doesn’t seem right as I know SimpleMembership changed a lot between MVC3 & 4 no?

  23. Thanks Le! I had come across that before in another MVC project with multiple contexts and required only one context to be part of migrations. The console is really good about the error message about multiple contexts also.

    I was trying to migrate two contexts in the same project and the console states migrations can be on for only one context in a project.

    This whole experiment was to work out the kinks integrating simpleMemberhship and some usefull application data as well.

    Again, great article which provides another vector to possible solutions :-)

  24. I refactored the UsersContext to hold any additional application entities and that works. I just learned migrations can be on for only one context in a project. Unless you have any insight. Thanks again.

    • Sam, you need to run migrations while explicitly specifying which context you are running it for, you can actually do migrations for more than one context.

      example: (from the package manager console):

      update-database -ConfigurationTypeName “”

  25. Oops. I wanted to add …. I’ve tried your solution out and it works. I thought I would try adding some additional model classes and context class. I found that EF Add-Migration doesn’t see the new model classes and pops up with the changes being empty. Is there something with multiple DBcontexts that I am implementing incorrectly?

    Cheers.

    • Sam,

      You need to make sure you have all your Entity Framework mapping classes implemented and these mapping classes need to be registered and added in the YourDbContext.OnModelCreating(DbModelBuilder builder) event.

      Example:

      
              protected override void OnModelCreating(DbModelBuilder builder)
              {
                  builder.Conventions.Remove<PluralizingTableNameConvention>();
                  builder.Configurations.Add(new DataAuditMap());
                  builder.Configurations.Add(new LogMap());
                  builder.Configurations.Add(new LogLevelMap());
      
                  base.OnModelCreating(builder);
              }
      
      
      
  26. hi,

    How do you move all database operations to a class library project? I’ve come far, but the webpages_roles etc are not created in the database.

    • Not sure I understand what you mean by move all database operations to a class library? Also please download the sample solution and make sure it runs correctly, webpages_roles should be created. You may want to start with a fresh new empty database first and run the project.

    • What i meant was, that i enabled migrations in a class library project. i’m trying to seperate database access and the web site. so i moved websecurity etc too. i also created a datacontext class. the problem i’m facing right now, is that ‘Roles’ doesn’t excist in the current context. Even though i added System.Web.Security. which is the namespace of it. Anything else i might be missing?

    • never mind, i didn’t referenced system.web in the project. somehow i thought i did.

  27. Le, many thanks – you have provided the most concise example of how to set up forms based security that I have found, saving a great deal of time.

    For those that have had issues such as Satish and Txumari – I experienced both of your problems. The root problem seems to be setting up the visual studio 2010 Server Explorer to look at the database.

    Following Le’s outline with out running Server explorer all works. However, depending on when you set up the Server Explorer I hit either Satish or Txumair’s issues. Simply put: Do not use Server Explorer with SQL Express in this example.

    One other small point, I did have to use SQL 2008 express configuration manager to enable a user of the form hostname\username. That is your laptop network name and your sign on name. This eliminated the error that demanded the database be initialized prior to use.

    Once again, many thanks
    T

  28. Pingback: .Vb? Of .C# | Thomas Site Building

  29. Hi. Thank you very much! I’ve spent 3 days on this task until I found your article. I had the same problem as txumari, but I think the reason was due to using default database before manipulations with it. There are no errors in a new created project !!!

  30. Pingback: Code first create tables

  31. Hi,

    Great tut!

    Suppose i want to add a table, How would i do that? I already tried to set up a table like the user profile, and did the update-database command. But at no avail…

  32. Hi Le
    thanks a million for your post, it was so helpfull. However i would like to ask you, if there is a way instead of adding fields to the Userprofile table to save information in fields in another table (for example a custom table or the webpages_membership table).

    I added 2 new fields (first name and last name) in the webpages_Membership table, sumbittted them with migrations, but saving them is not possible since they cannot be saved directly with the model.firstname since they are not in the UserProfile table.

    Any ideas?

    Again thanks for the awsome post!

    Tolis

  33. Hello!
    Thank you for this post – it was really helpful to me. Saved me a lot of time and nerve. :)
    Thank you!

    But, if we wanna add more “atributes” in dB, for example: BirthDate, LastName, FirstName ,… How to do that?
    I did try like adding the same way u add in your example PhoneNumber:

    AccountModel.cs
    …..
    [Table("UserProfile")]
    public class UserProfile
    {
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string UserEmail { get; set; }
    ……..

    Configuration.cs

    if (!WebSecurity.UserExists(“user123″))
    WebSecurity.CreateUserAndAccount(
    “user123″,
    “123456”,
    new { FirstName = “John” },
    new { LastName = “Kent” },
    new { UserEmail = “example@example.com” });
    …….
    But iv got error:
    “No overload for method ‘CreateUserAndAccount’ takes 5 arguments” – what I have to do that this code work?

  34. Hi,

    In you example, how you added the new field for Mobile data, how can you add this into the Manage action so the user can update that details freely?

  35. Hi Le,

    Sorry but I can keep answering my questions. The duplicate on the code worked. Should have tried before.

    The only thing pending is the [Administrator] not sure how to approach this.

    Thanks,

    Mark

  36. Hi le,
    Great tutorial, I got it running fast. I was wondering what do I need to do if I wanted to create a second role such as clients? Would it be with a dupplicate of the code in the web system.web

    and another basic question :) remember I’m new at this.

    You would use [Authorize] to allow regular users to that part of the code. How would you use the Administrator. would it be [Administrator]?

  37. Hi Le,

    Sorry if this is to basic but I’m new at this. On the first part of your tutorial ->
    “In the “System.Web” Section add:”

    How do you add code to the System. Web.

    Thanks,

    Mark

  38. Hi Le,

    I’ve read your article and it helped me a lot to get started with SimpleMembership. I’ve managed to implement SimpleMembership from scratch into a ASP.NET MVC 4 Basic Application, but I have a little issue yet.

    The problem is that to implement SimpleMembership I needed to use the InitializeSimpleMembershipAttribute that comes with the ASP.NET MVC 4 Internet Application and I’m not finding a cool way to use this with the Repository Pattern because it directly references one specific Context and specific name of table for users.

    Then at first I have two options: the first option is that on every single project I copy the Filter and change the configuration, directly referencing the context (which is not good, since I want to use repository pattern and interact with the context through the repository).

    The second option, I’ve tryed to generalize the filter to any context, passing it to the filter as a Type object, but it again directly references the context.

    Is there any better way to work with SimpleMembership and Repository Pattern in such a way that we get a good generalization, at the point that we can even move the filter to a separate assembly and reference it in any project ?

    Sorry if my question is silly, but I’m beginner with ASP.NET MVC and SimpleMembership and I’m still struggling with such issues.

    Thanks again for the article, your help and attention.

  39. Pingback: ASP.NET MVC4 – Restricting Access within your Web Site. | NoobSquad

  40. Hi this post has been really helpful, but i have a problem, I need to set up the membership and roles using a ModelFirst DB on another project on my solution and my Context is there so im not able to use migrations and when i try to initialize the web security it thows InvalidOperationException teling me that it can only be called once and if I delete de DB to crate it later it works but then the Role manager doesn’t work. I did every thing like you said but no results what do you think it might be

    • You may want to take a look at Filters/InitializeSimpleMembershipAttribute.cs, it’s being called there as well if this is an MVC 4 project.

  41. Anyone know where you configure the simplemembership (for password format etc?) is it to be done in web.config like before?

  42. Hello Le, Great Tutorial,

    I have a problem though. In your code example, you don’t declare your SimpleRoleProvider anywhere for the Seed method?

    So for me, the object Roles doesnt exist? what am i doing wrong?

    • I’ve solved that issue, but I get the same fault as paablo, even after referencing the version 2.0 of the WebMatrix.WebData.dll????

    • I’ve since figured this, Ive had to reference :-

      using System;
      using System.Data.Entity;
      using System.Data.Entity.Migrations;
      using System.Linq;
      using WebMatrix.WebData;
      using WebMatrix.Data;
      using System.Web;

  43. Great article but I also run into a problem where the Package Manager Console tells me that “To call this method, the “Membership.Provider” property must be an instance of “ExtendedMembershipProvider”.”

    Which is strange to me because I believe this happens when you call a method that you’re not supposed to from SimpleMembership. This happens when I do the update-database. I have nothing special in the Configuration file, just checking if some Role and User exist, and if not create them. Any idea?

  44. Pingback: Simple Membership Provider in MVC4 | knflinks

  45. how to do this with custom membership
    i.e

    –>

    where CustomMembership.Providers.Custom2 is

    public class Custom2 : WebMatrix.WebData.ExtendedMembershipProvider
    {
    // implemenet here
    }

    I tried but getting error

  46. I managed to fix the problem I was having. My project was referencing the wrong version of WebMatrix.WebData

  47. The code works great. All I have to do is alter the userprofile table to add the additional columns and then re-run PM>update-database -verbose and the seed data gets in.

  48. My answer to my question: using System.Web.Security in the Configuration.cs.

    Answer to the WebSecurity.InitializeDatabaseConnection error:
    Create _AppStart.cshtml file in the root and put only this code:ç

    @using WebMatrix.WebData;
    @{
    WebSecurity.InitializeDatabaseConnection(
    “Your_database”,
    “Your_table”,
    “UserId”,
    “UserName”, autoCreateTables: true);
    }

    Hope this helps

    • Thanks for taking the time to help us out onbermejo.
      I hope your advice helped Oscar.
      Unfortunately adding the reference to _AppStart.html did not make a difference. WebSecurity.InitializeDatabaseConnection just does not seem to run at all. I can put it in twice and not get a “you can only call once” error. Anyone who solves this will be my hero!

    • I don’t know, it’s working for me…
      I have followed the guide with the last update of the visual.

      Have you changed the webconfig?


      Have you done all the commands from Package Manager Console?

    • Yeah I have done all that stuff. There is more information on my stack overflow questions.
      Basically, if I hit debug, WebSecurity.InitializeDatabaseConnection is called as expected. If I run “Update-Database” it doesn’t seem to get called anywhere, hence the error.
      The only difference with my project really is that my project is split into a Domain and a WebUI project for the separate layers.

    • After creating a new C# MVC4 application in VS 2012, for migrations and simplemembership, do the following

      1. Check the Connection String in the web.config. If using Machine\SQLExpress

      2. In Web.Config

      3. After PM> enable-migrations, in Configuration.cs

      #region

      using System;
      using System.Data.Entity;
      using System.Data.Entity.Migrations;
      using System.Linq;
      using System.Web.Security;
      using TSBVISTP.Models;
      using WebMatrix.WebData;
      using System.Collections.Generic;

      #endregion

      namespace TSBVISTP.Migrations
      {
      internal sealed class Configuration : DbMigrationsConfiguration
      {
      public Configuration()
      {
      AutomaticMigrationsEnabled = true;
      }

      protected override void Seed(STPDBContext context)
      {
      // This method will be called after migrating to the latest version.

      // You can use the DbSet.AddOrUpdate() helper extension method
      // to avoid creating duplicate seed data. E.g.
      //
      // context.People.AddOrUpdate(
      // p => p.FullName,
      // new Person { FullName = “Andrew Peters” },
      // new Person { FullName = “Brice Lambson” },
      // new Person { FullName = “Rowan Miller” }
      // );
      //
      WebSecurity.InitializeDatabaseConnection(“DefaultConnection”, “UserProfile”, “UserId”, “UserName”,
      autoCreateTables: true);
      if (!Roles.RoleExists(“Administrator”))
      Roles.CreateRole(“Administrator”);
      if (!WebSecurity.UserExists(“UserGA”))
      WebSecurity.CreateUserAndAccount(“UserGA”, “password”,
      new
      {
      FirstName = “User”,
      LastName = “GA”,
      userAddress = “123 something dr”,
      userCity = “Austin”,
      userZip = “78750”,
      WorkPhone = “512-555-5555″,
      AlternatePhone = “512-668-7898″,
      FaxNumber = “512-232-1212″,
      EmailAddress = “Simitt@gmail.com”
      }, false);
      if (!Roles.GetRolesForUser(“UserGA”).Contains(“Administrator”))
      Roles.AddUsersToRoles(new[] {“UserGA”}, new[] {“Administrator”});

      //var students = new List
      //{
      // new Student { FirstMidName = “Carson”, LastName = “Alexander”, EnrollmentDate = DateTime.Parse(“2005-09-01″) },
      // new Student { FirstMidName = “Meredith”, LastName = “Alonso”, EnrollmentDate = DateTime.Parse(“2002-09-01″) },
      // new Student { FirstMidName = “Arturo”, LastName = “Anand”, EnrollmentDate = DateTime.Parse(“2003-09-01″) },
      // new Student { FirstMidName = “Gytis”, LastName = “Barzdukas”, EnrollmentDate = DateTime.Parse(“2002-09-01″) },
      // new Student { FirstMidName = “Yan”, LastName = “Li”, EnrollmentDate = DateTime.Parse(“2002-09-01″) },
      // new Student { FirstMidName = “Peggy”, LastName = “Justice”, EnrollmentDate = DateTime.Parse(“2001-09-01″) },
      // new Student { FirstMidName = “Laura”, LastName = “Norman”, EnrollmentDate = DateTime.Parse(“2003-09-01″) },
      // new Student { FirstMidName = “Nino”, LastName = “Olivetto”, EnrollmentDate = DateTime.Parse(“2005-09-01″) }
      //};
      //students.ForEach(s => context.Students.Add(s));
      //context.SaveChanges();

      //var Staffs = new List
      //{
      // new Staff { FirstMidName = “Kim”, LastName = “Abercrombie”, HireDate = DateTime.Parse(“1995-03-11″) },
      // new Staff { FirstMidName = “Fadi”, LastName = “Fakhouri”, HireDate = DateTime.Parse(“2002-07-06″) },
      // new Staff { FirstMidName = “Roger”, LastName = “Harui”, HireDate = DateTime.Parse(“1998-07-01″) },
      // new Staff { FirstMidName = “Candace”, LastName = “Kapoor”, HireDate = DateTime.Parse(“2001-01-15″) },
      // new Staff { FirstMidName = “Roger”, LastName = “Zheng”, HireDate = DateTime.Parse(“2004-02-12″) }
      //};
      //Staffs.ForEach(s => context.Staffs.Add(s));
      //context.SaveChanges();

      //var departments = new List
      //{
      // new Department { Name = “English”, Budget = 350000, StartDate = DateTime.Parse(“2007-09-01″), PersonId = 9 },
      // new Department { Name = “Mathematics”, Budget = 100000, StartDate = DateTime.Parse(“2007-09-01″), PersonId = 10 },
      // new Department { Name = “Engineering”, Budget = 350000, StartDate = DateTime.Parse(“2007-09-01″), PersonId = 11 },
      // new Department { Name = “Economics”, Budget = 100000, StartDate = DateTime.Parse(“2007-09-01″), PersonId = 12 }
      //};
      //departments.ForEach(s => context.Departments.Add(s));
      //context.SaveChanges();

      //var programs = new List
      //{
      // new Program { ProgramId = 1050, Title = “ASE”, Credits = 3, DepartmentId = 3, Staffs = new List() },
      // new Program { ProgramId = 4022, Title = “ESC2″, Credits = 3, DepartmentId = 4, Staffs = new List() },
      // new Program { ProgramId = 4041, Title = “SWEAT”, Credits = 3, DepartmentId = 4, Staffs = new List() },
      // new Program { ProgramId = 1045, Title = “ESE”, Credits = 4, DepartmentId = 2, Staffs = new List() },
      // new Program { ProgramId = 3141, Title = “ASE2″, Credits = 4, DepartmentId = 2, Staffs = new List() },
      // new Program { ProgramId = 2021, Title = “SWT”, Credits = 3, DepartmentId = 1, Staffs = new List() },
      // new Program { ProgramId = 2042, Title = “ABC”, Credits = 4, DepartmentId = 1, Staffs = new List() }
      //};
      //programs.ForEach(s => context.Programs.Add(s));
      //context.SaveChanges();

      //programs[0].Staffs.Add(Staffs[0]);
      //programs[1].Staffs.Add(Staffs[1]);
      //programs[2].Staffs.Add(Staffs[2]);
      //programs[3].Staffs.Add(Staffs[2]);
      //programs[4].Staffs.Add(Staffs[3]);
      //programs[5].Staffs.Add(Staffs[3]);
      //programs[6].Staffs.Add(Staffs[3]);
      //programs[7].Staffs.Add(Staffs[3]);
      //context.SaveChanges();

      //var enrollments = new List
      //{
      // new Enrollment { PersonId = 1, ProgramId = 1050, Grade = 1 },
      // new Enrollment { PersonId = 1, ProgramId = 4022, Grade = 3 },
      // new Enrollment { PersonId = 1, ProgramId = 4041, Grade = 1 },
      // new Enrollment { PersonId = 2, ProgramId = 1045, Grade = 2 },
      // new Enrollment { PersonId = 2, ProgramId = 3141, Grade = 4 },
      // new Enrollment { PersonId = 2, ProgramId = 2021, Grade = 4 },
      // new Enrollment { PersonId = 3, ProgramId = 1050 },
      // new Enrollment { PersonId = 4, ProgramId = 1050, },
      // new Enrollment { PersonId = 4, ProgramId = 4022, Grade = 4 },
      // new Enrollment { PersonId = 5, ProgramId = 4041, Grade = 3 },
      // new Enrollment { PersonId = 6, ProgramId = 1045 },
      // new Enrollment { PersonId = 7, ProgramId = 3141, Grade = 2 },
      //};
      //enrollments.ForEach(s => context.Enrollments.Add(s));
      //context.SaveChanges();

      //var officeAssignments = new List
      //{
      // new ClassAssignment { PersonID = 9, Location = “Class 1″ },
      // new ClassAssignment { PersonID = 10, Location = “Class 27″ },
      // new ClassAssignment { PersonID = 11, Location = “Class 304″ },
      //};
      //officeAssignments.ForEach(s => context.OfficeAssignments.Add(s));
      //context.SaveChanges();

      var menus = new List
      {
      new Menu {Id = 1, Name = “Main”, MenuItems = new List()},

      };
      menus.ForEach(s => context.Menus.Add(s));
      context.SaveChanges();

      var menuitems = new List
      {
      new MenuItem
      {
      Id = 1,
      Name = “Home”,
      ActionName = “Index”,
      ControllerName = “Home”,
      Url = “”,
      ParentMenu = menus[0]
      },
      new MenuItem
      {
      Id = 2,
      Name = “Student”,
      ActionName = “Index”,
      ControllerName = “Student”,
      Url = “”,
      ParentMenu = menus[0]
      },
      new MenuItem
      {
      Id = 3,
      Name = “Staff”,
      ActionName = “Index”,
      ControllerName = “Staff”,
      Url = “”,
      ParentMenu = menus[0]
      },
      new MenuItem
      {
      Id = 4,
      Name = “Programs”,
      ActionName = “Index”,
      ControllerName = “Program”,
      Url = “”,
      ParentMenu = menus[0]
      },
      new MenuItem
      {
      Id = 5,
      Name = “Residential”,
      ActionName = “Index”,
      ControllerName = “Department”,
      ParentMenu = menus[0]
      },
      new MenuItem
      {
      Id = 6,
      Name = “About”,
      ActionName = “About”,
      ControllerName = “Home”,
      Url = “”,
      ParentMenu = menus[0]
      },
      new MenuItem
      {
      Id = 7,
      Name = “Contact”,
      ActionName = “Contact”,
      ControllerName = “Home”,
      Url = “”,
      ParentMenu = menus[0]
      },
      };
      menuitems.ForEach(s => context.MenuItems.Add(s));
      context.SaveChanges();

      }
      }
      }

      4. update-database -verbose

      5. In SQL run update query to add columns

      GO
      ALTER TABLE [dbo].[UserProfile]
      ADD [FirstName] VARCHAR (50) NULL,
      [LastName] NVARCHAR (50) NULL,
      [userAddress] NVARCHAR (50) NULL,
      [userCity] NVARCHAR (50) NULL,
      [userZip] NVARCHAR (50) NULL,
      [WorkPhone] NVARCHAR (50) NULL,
      [AlternatePhone] NVARCHAR (50) NULL,
      [FaxNumber] NVARCHAR (50) NULL,
      [EmailAddress] NVARCHAR (50) NULL;

      6. PM> update-database -verbose

      you must see migrations working.now.

  49. Your sample app works fine. I am currently running it on the side of my project trying to work out the differences with no luck.

  50. Any Idea why I cannot apply this code example (that I can confirm works) to my own project? This is starting to drive me insane. Something so simple should not be this complicated. I can place the InitializeDatabaseConnection code more than once and it won’t throw the “InitializeDatabaseConnection has already been called” error. Really need help with this one.

    • Hi paablo,

      Could you first confirm that the sample application works before implementing this into your solution? After doing so let me know and I try to guide you to integrating it into your project.

  51. The explanation refers to changing the ‘User’ table yet the code still refers to the ‘Userprofile’ table !!. So yes this will all work except when it comes to retrieveing the value of the additional profile fields. as this still points at the ‘Userprofile’ table which hasn’t been extended or populated !!.

    Example Code of Retrieving Profile Fied Values::

    if (oSettings.Alert_Required_Locations_Changes)
    {
    using (var context = new UsersContext())
    {
    var profile = context.UserProfiles.SingleOrDefault(x => x.UserName == User.Identity.Name);
    if (profile.Email.IsNotNullOrEmpty())
    {

    EMail.sendEmail(CONFIRM_LOCATION_REQUIRED, CONFIRM_CREATE_TO_BE_VALIDATED, profile.Email);
    }
    }
    }

  52. I get the same “You must call the “WebSecurity.InitializeDatabaseConnection” method before you call any other method of the “WebSecurity” class. This call should be placed in an _AppStart.cshtml file in the root of your site.” if I try and seed users/roles inside my initiation method via Update-Database. This error does not appear if I remove the seeding code, and I already call the WebSecurity.InitializeDatabaseConnection method in my Global.asax.cs.

  53. I try to pass the las paremeter false, but I get the same error. Furthermore if my database exists without the new field “email” and I put a “false” how can I update my database?

    • Hi txumari,

      For a sanity check could you please download and run the sample application just to validate that it works first?

  54. When i try to run i get the following error am i missing anything?
    You must call the “WebSecurity.InitializeDatabaseConnection” method before you call any other method of the “WebSecurity” class. This call should be placed in an _AppStart.cshtml file in the root of your site.

    I followed your steps

    • Here is the actual error

      Running Seed method.
      System.InvalidOperationException: You must call the “WebSecurity.InitializeDatabaseConnection” method before you call any other method of the “WebSecurity” class. This call should be placed in an _AppStart.cshtml file in the root of your site.
      at WebMatrix.WebData.SimpleRoleProvider.get_PreviousProvider()
      at WebMatrix.WebData.SimpleRoleProvider.RoleExists(String roleName)
      at System.Web.Security.Roles.RoleExists(String roleName)
      at StreamingAdmin.Migrations.Configuration.Seed(StreamingDBContext context) in C:\Satish\StreamingAdmin\StreamingAdmin\Migrations\Configuration.cs:line 35
      at System.Data.Entity.Migrations.DbMigrationsConfiguration`1.OnSeed(DbContext context)
      at System.Data.Entity.Migrations.DbMigrator.SeedDatabase()
      at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.SeedDatabase()
      at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
      at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
      at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
      at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
      at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore()
      at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()
      You must call the “WebSecurity.InitializeDatabaseConnection” method before you call any other method of the “WebSecurity” class. This call should be placed in an _AppStart.cshtml file in the root of your site.

    • satish, paablo: I had the same issue but sorted by adding the following line of code (same as in Configuration.cs) in Application_Start() method in my Global.asax.cs WebSecurity.InitializeDatabaseConnection(“DefaultConnection”, “Users”, “Id”, “UserName”, false);

  55. This post was a ‘SUPERGLUE’ for my work.
    Saved me many days of frustration.
    Thank you very very very much.
    May God Bless You.

    • Hi txumari,

      You will can pass in false for the last parameter if your table already exists.

      
      WebSecurity.InitializeDatabaseConnection("MyDataContext", "User", "Id", "Username", false);
      
      
  56. I’m trying this but when I try to update-database -verbose, return and error “Ya hay un objeto con el nombre ‘UserProfile’ en la base de datos.”

  57. Hi Le, thanks for this. This is very useful.

    I have a question: is the InitializeSimpleMembership attribute in the AccountController class still needed or can it be deleted? Thanks

    • Hi Jeremiah,

      You can delete it, as long as you are calling WebSecurity.CreateUserAndAccount method from you Seed method in your /MIgrations/Configuration.cs class as illustrated in this blog post.

  58. Pingback: The term ‘enable-migration’ is not recognized as the name of a cmdlet, function, script file, or operable program. | | Yasser ShaikhYasser Shaikh

  59. Hi Le will you be able to help me a bit and advice me on the best way I should allow the user to vie his details and edit them later if he requires. Also give him the chance to unsubscribe. Thank you very much in advance!

  60. Thank you Le I managed doing it as you say also adding
    WebSecurity.CreateUserAndAccount(
    model.UserName,
    model.Password,
    new {FirstName = model.FirstName,
    LastName = model.LastName,
    City = model.City,
    ZIP = model.ZIP,
    Street = model.Street,
    StreetNumber = model.StreetNumber,
    Country = model.Country}, false
    );
    and it works perfectly. Now I need to work on the admin being able to edit these parameters. Thanks for the reply.

  61. Hi great work really helpful. Would you be so kind to let me know if i would like to input more fields how can i work around the WebSecurity.CreateUserAndAccount(…….) for example I would like to input
    model.UserName,
    model.Password,
    model.FirstName,
    model.LastName );

    Please any suggestion would be helpful and thanks in advance for any help! Regards, Ilia

    • Hi Ilia,

      You will need to create those fields in your the user table you are using.

      You can get those values in by using a dynamic object/class as the last parameter in the WebSecurity.CreateUserAndAccount method.

      
                  if (!WebSecurity.UserExists("lelong37@gmail.com"))
                      WebSecurity.CreateUserAndAccount(
                          "lelong37@gmail.com", 
                          "password", 
                          new
                              {
                                  FirstName = model.FirstName,
                                  LastName = model.LastName,
                                  Created = DateTime.Now, 
                                  Updated = DateTime.Now
                              });
      
      
    • Hi David, you will need to create a view that with with a minimum of two text fields e.g. Username and Password. In your controller action or service that your injecting to invoke the WebSecurity.CreatUserAndAccount method.

      
      WebSecurity.CreateUserAndAccount("lelong37@gmail.com", "mypassword");
      
      

      SimpleMembershipProvider does not support the ASP.NET Configuration Site, the out of the box Admin screens that you can use to manage User, Roles, and Permissions with the other providers.

  62. Hi, thanks for the good post. I have made use of this in my work.

    I would like to clarify, if I wanted to use the email field in place of the user name, would I change:

    WebSecurity.InitializeDatabaseFile(“SecurityDemo.sdf”, “Users”, “UserID”, “Username”, true);

    to:

    WebSecurity.InitializeDatabaseFile(“SecurityDemo.sdf”, “Users”, “UserID”, “Email”, true);

    Then, within my MVC 4 app, in the account controller, login action I would place:

    if (ModelState.IsValid && WebSecurity.Login(model.Email, model.Password, persistCookie: model.RememberMe))

    {

    return RedirectToLocal(returnUrl);

    }

    I would continue this, matching up the web security username with the user model email e.g:

    private static string ErrorCodeToString(MembershipCreateStatus createStatus)

    {

    // See go.microsoft.com/fwlink for

    // a full list of status codes.

    switch (createStatus)

    {

    case MembershipCreateStatus.DuplicateUserName:

    return “An account with that email already exists. Please use a different email or contact info@moneydrainplug.com.”;

    .

    .

    .

    Apologies for the long post and all the code, I hope it is still legible.

    Thanks

  63. I just tried the sample of your link and could not download could you please provide the sample code again thanks

  64. Pingback: Patrick Desjardins' Blog » Asp.Net MemberShip with MVC4

  65. Hi Le,

    I’ve gone through, and created a project based on the membership samples you’ve given here and begun to expand on it to include related tables.. However it seems the WebSecurity.CreateUserAndAccount method chokes when we have a self-defined ‘User’ table with foreign keys.

    I have one-to-one and many-to-many relationships defined, and both cause errors similar to this: System.Data.SqlClient.SqlException (0x80131904): Invalid column name ‘PlayingTeams’.

    PlayingTeams is a virtual ICollection and I’ve set up mapping like this in the OnModelCreating method:

    modelBuilder.Entity()
    .HasMany(t => t.Players)
    .WithMany(p => p.PlayingTeams)
    .Map(mc =>
    {
    mc.ToTable(“TeamPlayers”);
    mc.MapLeftKey(“UserProfileId”);
    mc.MapRightKey(“TeamId”);
    });

    What do you think..? Is there something missing, or are you perhaps aware of a limitation in the design of this?

    Cheers, Aaron

    • Hi Aron,

      I’m unaware of why this might be happening, currently my User table has foreign keys, however just not with a many-to-many relationship, and instead a one-to-one relationship. However looking at your modelBuilder code, it looks like you can’t insert a Player without inserting the user into a PlayingTeam, the WebSecurity.CreateUserAndAccount will not do this. You can test this theory by temporarily removing the many-to-many.

    • Hi Le,

      Sorry for not writing earlier, I just returned from a short and much-needed break :-)

      I will check this out in the evening and see what sticks with some different approaches and write back afterwards.

      Perhaps you’re right about the model builder code and I need to learn a bit more about how this fluent API works.

      Cheers,
      – Aaron

    • Peter,

      Thanks! So far the only way I know of at the moment, is to actually access custom user properties using EntityFramework itself.

    • Hi Le,

      I have implemented your sample, and it Works perfektly – thanks for sharing :-)
      Do you know of any way to get the Id of a user from inside MVC4 so that I can use the .Find method of the DBContext or do I have to create a query searching for the UserName…

      /re. Peter

    • Peter,

      You are on the right track, you will have to query the UserProfile table using EntityFramework (your DBContext) by username.

  66. Pingback: Multi-Step ASP.NET MVC 4 Registration with SMS using Twilio Cloud Communication and SimpleMembershipProvider for Increased User Validity « Long Le's Blog

Please Leave a Reply or Tweet me @LeLong37...!

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s