How do you design your code-first approach in entity framework when your code should include user data (name, password...) without repeating/overwriting what the MVC framework will generate in terms of user tables, classes, authorization and authentication
As simple example, if i have an application that will manage user projects, my models will contain the following classes, and have the following relationship:
- One user may be assigned one or MANY projects
- One project may be assigned to one or MANY users
( just to show the many to many ERD relationship nature)
class User{
//implementation of the class members and
// navigation properties to alow Entity Framework to create the DB tables
}
class Project{
//implementation of the class members and
// navigation properties to alow Entity Framework to create the DB tables
}
Now the problem i am facing is that EF and ASP .net MVC framework takes care of creating user tables, profiles and roles entities...
I am not sure whether it is possible to design my classes in a way to show an automatic (conventional) relationship with the rest of the tables created by MVC.
In the case this needs to be done by writting custom Authentication classes, can you please explain how? because i have found many articles that discuss the same issue but without pointing out the relationship between the project classes and the MVC created classes / tables, plus if the developer choses to use the MVC way he will end up with two data contexts, even after merging both tables in one sql server catalog.
2 Answers 2
If I'm reading your question correctly, then what you're looking for is SimpleMembership.
Here's an explanation of SimpleMembership; from the section Easy to with[sic] Entity Framework Code First:
SimpleMembership ... allows[changed] you to use any table as a user store. That means you're in control of the user profile information, and you can access it however you'd like ....
So you can define your own User
class to hold extra user data and relationships, e.g.:
[Table("UserProfile")]
public class UserProfile
{
// required fields:
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
// your extra fields:
public List<Project> Projects { get; set; }
// more here...
}
and the regular, built-in Membership stuff is used for handling logins, passwords, and everything else behind the scenes.
There's a little more to be done to integrate it, but it wasn't too bad when I used it.
Note that this works from MVC4 on.
Edit to address questions asked in the comments:
From what I can tell looking at my code (it's been a while since I worked on the project and, between it being my first MVC project and other projects scrambling my brain since then, things are a bit fuzzy):
It looks like I ended up creating my own context that inherited from the DbContext
class (as outlined in this tutorial) and contained all my application data; e.g.:
public class MyContext : DbContext
{
public MyContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<Projects> Projects { get; set; }
// more here
}
(IIRC, by inheriting from the DbContext
type we get all the built-in membership stuff.)
Then the rest of the app had to be configured to use this context (as given in the tutorial). (All of my controllers create an instance of my derived context, but this could be set up using dependency injection as well.)
It looks like the database connection is initialized in the InitializeSimpleMembershipAttribute
by default -- this attribute gets applied to all the controllers.
I ran into the issue stated in this question with this setup, so to fix it I followed the advice in the accepted answer and moved the database connection initialization code to a central point (Global.asax.cs) that ran only once when the web app started.
I'm afraid that I can't remember many more details than this, so you'll probably have to do a bit more research (and probably troubleshooting) to get this working, but it should give you a decent idea of what to look for.
I ended up reading a lot of tutorials on asp.net, so you might check that site out if you've not already.
-
thanks for the link, this looks exactly what i am looking for with one exception, i believe, i still need to deal with two separate data contexts, userscontext and the application context. but it's a great step, if you do not mind, since you've used it before, did you manage to get all your entities (app classes, and membership classes) using the same datacontext? for initialization and queries...? Thanksjoe– joe2014年09月04日 21:52:11 +00:00Commented Sep 4, 2014 at 21:52
-
@joe I updated my answer to answer your questions -- there was too much for just a comment.paul– paul2014年09月05日 13:26:06 +00:00Commented Sep 5, 2014 at 13:26
Here is how you can accomplish this.
I am going to explain a way in which you can utilize existed Asp.Net Mvc Accounts Tables even plus you can add further into them as well as per your requirements.
First you need to install following Packages.
Install-Package Microsoft.AspNet.Identity
Install-Package Microsoft.AspNet.Identity.EntityFramework
Now you would have to do further as follows.
First Of All Asp.Net Identity provides a table IdentityUser which contains following properties
Id,UserName,PasswordHash,SecurityStamp,Discriminator
Suppose I want to add further properties to i can do that by Creating a class and Inheriting it from IdentityUser
Here is example lets say I call it Client.
public class Client:IdentityUser
{
//Suppose I want to add Further Properties to to my IdentityUser
//table provided by Asp.Net by default.
//suppose i want Email,Date Birth.
[Required]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[Display(Name = "BirthDate")]
public DateTime BirthDate { get; set; }
}
Now Create Your Model classes Lets say in my case One User can have many Projects.
public class Project
{
//Now all your properties will go here
// plus now you can connect projects to IdentityUser
//by using Client class which is inherited from IdentityUser.
public virtual Client Client{get; set;}
}
Your further model classes will go here.
public class SecondModelClass
{
}
Now Go to your context rather than inheriting it from DbContext you can inherit it from IdentityDbContext here is sample code below.
//Notice I am passing it Client class which was inherited from IdentityUser
public class YourContextName:IdentityDbContext<Client>
{
public YourContextName():base("connectionStringName")
{
}
public class IdentityUserLoginConfiguration : EntityTypeConfiguration<IdentityUserLogin>
{
public IdentityUserLoginConfiguration()
{
HasKey(iul => iul.UserId);
}
}
public class IdentityUserRoleConfiguration : EntityTypeConfiguration<IdentityUserRole>
{
public IdentityUserRoleConfiguration()
{
HasKey(iur => iur.RoleId);
}
}
public DbSet<Project> Projects { get; set; }
public DbSet<ModelClass2> AnyName { get; set; }
public DbSet<ModelClass3> MoreClassesName { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new IdentityUserLoginConfiguration());
modelBuilder.Configurations.Add(new IdentityUserRoleConfiguration());
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Now it you entire AccountController you would have to pass your Client class inherited from IdentityUser
public class AccountController : Controller
{
public AccountController()
: this(new UserManager<Client>(new UserStore<Client>(new Context.YourContextName())))
{
}
public AccountController(UserManager<Client> userManager)
{
UserManager = userManager;
}
public UserManager<Client> UserManager { get; private set; }
//Further Code Will go below here........................
//
}
This solution will utilize everything provided by Asp.Net Identity plus Your customization as well.
Cheers.
-
very detailed, thanks i will consider your approach.joe– joe2014年09月06日 18:59:42 +00:00Commented Sep 6, 2014 at 18:59
-
plz let me know if you found any issues in this i am willing to help you.Husrat Mehmood– Husrat Mehmood2014年09月07日 03:08:53 +00:00Commented Sep 7, 2014 at 3:08
-
Hi joe have you solved your issue the way i suggested you above plz let me knowHusrat Mehmood– Husrat Mehmood2014年09月09日 09:22:15 +00:00Commented Sep 9, 2014 at 9:22
Explore related questions
See similar questions with these tags.
User
class, how would you go about adding these new features?