Search code examples
asp.net-mvcentity-frameworksimplemembership

Entity Framework Code First with SimpleMembershipProvider


I have two projects inside one solution:

  1. foo.Domain (Class Library, my entities and DBContext are in here)
  2. foo.WebUI (ASP.NET MVC 4.5, empty template)

Inside foo.Domain i create my entities and translate them into actual database using Entity Framework.

I've been searching online on how I can create a custom membership feature with register, login functions etc using entity framework code first and built in simplemembershipprovider in ASP.NET MVC 4, but most of the demo online used entity framework inside foo.WebUI and migrations are all inside foo.WebUI without using a foo.Domain class library, if i do it that way, i am going to end up having two separate migrations inside foo.Domain(other entities) and foo.WebUI(user+role entities). I am very confused to what I should do, hope what i say makes sense.


Solution

  • Assuming that you have in foo.Domain the following tables that will manage the security things:

    1. Users ( having at least Id,UserName,Password, and IsActive)
    2. Roles ( Id, Name of the role)
    3. UserRoles ( Having RoleId, UserId)

    then you can do the following:

    1- add a class call it (CustomMembership) containing the following

    2- add refernece to WebMatrix.WebData in order to use the simple membership provider

     public class CustomMembership : SimpleMembershipProvider
        {
    
            public override bool ValidateUser(string username, string password)
            {
                if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
                    return false;
                using (var context = new Entities()) // Entities is your Context
                {
                    string encryptedPassword = Encrypt(password); // Encryt is used for comparing the entered password with the encrypted password stored in db
                    var item = context.Users.Where(t => t.UserName.ToLower() == username.ToLower()
                        && t.Password == encryptedPassword
                        && t.IsActive).FirstOrDefault();
                    return item != null;
    
                }
            }
        }
    

    3- add class called CustomRoleManager contianing the following:

    public class CustomRoleManager : SimpleRoleProvider
        {
            public override bool IsUserInRole(string username, string roleName)
            {
                using (var context = new Entities())
                {
                    var result = context.UserRoles.FirstOrDefault(t => t.Role.Name == roleName
                        && t.User.UserName.ToLower() == username.ToLower()
                        && t.User.IsActive);
                    return result != null;
                }
            }
    
            public override string[] GetAllRoles()
            {
                using (var context = new Entities())
                {
                    var result = context.Roles.Select(t => t.Name).ToArray();
                    return result;
                }
            }
    
            public override string[] GetRolesForUser(string username)
            {
                using (var context = new Entities())
                {
                    var result = (from ur in context.UserRoles
                                  join u in context.Users on ur.UserId equals u.Id
                                  join r in context.Roles on ur.RoleId equals r.Id
                                  where u.UserName.ToLower() == username.ToLower()
                                  && u.IsActive
                                  select r.Name).ToArray();
                    return result;
                }
            }
        }
    

    4- add the following in the Web.Config file, note that you should add the full path of the classes, here i put foo.WebUI

    this step is to tell your application to use the custom membership and custom role manager

    <roleManager enabled="true" defaultProvider="CustomRoleManager" cacheRolesInCookie="true">
          <providers>
            <clear />
            <add name="CustomRoleManager" type="foo.WebUI.CustomRoleManager" />
          </providers>
        </roleManager>
        <membership defaultProvider="CustomMembership" userIsOnlineTimeWindow="10">
          <providers>
            <clear />
            <add name="CustomMembership" type="foo.WebUI.CustomMembership" connectionStringName="ConnectionString" enablePasswordRetrieval="false" enablePasswordReset="false" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/" />
          </providers>
        </membership>
    

    5- maybe you need to add the following keys in the app settings in web.config file to avoid errors

    <add key="enableSimpleMembership" value="false" />
    <add key="autoFormsAuthentication" value="false" />
    

    hope this will help you