I have two projects inside one solution:
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.
Assuming that you have in foo.Domain the following tables that will manage the security things:
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