ASP.NET Identity with EF Database First MVC5
It should be possible to use the identity system with POCO and Database First, but you'll have to make a couple of tweaks:
- Update the .tt-file for POCO generation to make the entity classes
partial
. That will make it possible for you to supply additional implementation in a separate file. - Make a partial implementation of the
User
class in another file
partial User : IUser
{
}
That will make the User
class implement the right interface, without touching the actual generated files (editing generated files is always a bad idea).
My steps are very similar but I wanted to share.
1) Create a new MVC5 project
2) Create a new Model.edmx. Even if it's a new database and has no tables.
3) Edit web.config and replace this generated connectionstring:
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-SSFInventory-20140521115734.mdf;Initial Catalog=aspnet-SSFInventory-20140521115734;Integrated Security=True" providerName="System.Data.SqlClient" />
with this connectionstring:
<add name="DefaultConnection" connectionString="Data Source=.\SQLExpress;database=SSFInventory;integrated security=true;" providerName="System.Data.SqlClient" />
Afterwards, build and run the application. Register a user and then the tables will be created.
EDIT: ASP.NET Identity with EF Database First for MVC5 CodePlex Project Template.
I wanted to use an existing database and create relationships with ApplicationUser. This is how I did it using SQL Server but the same idea would probably work with any DB.
- Create an MVC Project
- Open the DB listed under the DefaultConnection in Web.config. It will be called (aspnet-[timestamp] or something like that.)
- Script the database tables.
- Insert the scripted tables into existing database in SQL Server Management Studio.
- Customize and add relationships to ApplicationUser (if necessary).
- Create new Web Project > MVC > DB First Project > Import DB with EF ... Excluding the Identity Classes you inserted.
- In IdentityModels.cs change the ApplicationDbContext
:base("DefaltConnection")
to use your project's DbContext.
Edit: Asp.Net Identity Class Diagram
IdentityUser
is worthless here because it's the code-first object used by the UserStore
for authentication. After defining my own User
object, I implemented a partial class that implements IUser
which is used by the UserManager
class. I wanted my Id
s to be int
instead of string so I just return the UserID's toString(). Similarly I wanted n
in Username
to be uncapitalized.
public partial class User : IUser
{
public string Id
{
get { return this.UserID.ToString(); }
}
public string UserName
{
get
{
return this.Username;
}
set
{
this.Username = value;
}
}
}
You by no means need IUser
. It's only an interface used by the UserManager
. So if you want to define a different "IUser" you would have to rewrite this class to use your own implementation.
public class UserManager<TUser> : IDisposable where TUser: IUser
You now write your own UserStore
which handles all of the storage of users, claims, roles, etc. Implement the interfaces of everything that the code-first UserStore
does and change where TUser : IdentityUser
to where TUser : User
where "User" is your entity object
public class MyUserStore<TUser> : IUserLoginStore<TUser>, IUserClaimStore<TUser>, IUserRoleStore<TUser>, IUserPasswordStore<TUser>, IUserSecurityStampStore<TUser>, IUserStore<TUser>, IDisposable where TUser : User
{
private readonly MyAppEntities _context;
public MyUserStore(MyAppEntities dbContext)
{
_context = dbContext;
}
//Interface definitions
}
Here are a couple examples on some of the interface implementations
async Task IUserStore<TUser>.CreateAsync(TUser user)
{
user.CreatedDate = DateTime.Now;
_context.Users.Add(user);
await _context.SaveChangesAsync();
}
async Task IUserStore<TUser>.DeleteAsync(TUser user)
{
_context.Users.Remove(user);
await _context.SaveChangesAsync();
}
Using the MVC 5 template, I changed the AccountController
to look like this.
public AccountController()
: this(new UserManager<User>(new MyUserStore<User>(new MyAppEntities())))
{
}
Now logging in should work with your own tables.