I'm currently developing a web application. I'm using Identity for the authentication and roles of my user.
I want each user in my application to have an associated "Institution". This Institution contains a Name and a Description. Here is my IdentityUser class:
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
[Display(Name="Institution")]
public Institution Institution { get; set; }
}
When I update my database, the Seed method is executed, and this one, I'm creating a User with the "admin" roles and I associate an Institution. Here is my Seed method:
if (!context.Users.Any(u => u.UserName == "mxfragz"))
{
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new IdentitiesDb()));
roleManager.Create(new IdentityRole("admin"));
var store = new UserStore<ApplicationUser>(context);
var manager = new UserManager<ApplicationUser>(store);
var user = new ApplicationUser { UserName = "mxfragz" };
user.Institution = new Institution() { Name = "London", Description="Description" };
manager.Create(user, "password");
manager.AddToRole(user.Id, "admin");
}
My problem is that, when I'm creating a new User in my web application, I can't find a way to associate an existing Institution (here only "London" is created). With what I've done so far, when I create a user, I get the ID of the selected Institution and find an existing Institution in order to associate it with the Institution property defined in my user. When I do so, instead of associating the existing Institution that has been found, entity framework creates a new one, and associate it to my User. I end up with 2 different Institutions with the same Name and Description. Here is my code:
public async Task<ActionResult> Create(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser() { UserName = model.Username, Email = string.Empty };
int selected = int.Parse(model.SelectedInstitution);
user.Institution = new InstitutionsDb().Institutions.Where(x => x.Id == selected).First();
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new IdentitiesDb()));
UserManager.AddToRole(user.Id.ToString(), roleManager.Roles.Where(x => x.Id == model.SelectedRole.ToString()).First().Name);
return RedirectToAction("Index", "Users");
}
else
{
AddErrors(result);
}
}
model.Roles = GetRoles();
model.Institutions = GetInstitutions();
return View(model);
}
I found several topics about using the Attach method, but even when I tried with it, it didn't work. Am I doing something wrong ? Or is there any way to do what I want to do ?
user.Institutionbut also expose the foreign key in your model, (user.InstitutionId?) and set its value.user.Institution.Name).Institutionto theUserManagerfirst, but I don't know if that's possible (I don't know this UserManager very well).ApplicationUserobjects to anApplicationUserscollection (if present) of an attachedInstitution.