Reputation: 536
Using MVC5 code first approach.
I haven't changed the user store, added a property called Name in ApplicationUser Class. So it looks like as follows : -
public class ApplicationUser : IdentityUser
{
[Required]
[StringLength(100)]
public string Name { get; set; }
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;
}
}
I have a company class, which looks like below :-
public class Company
{
public int Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
}
A company will definitely has more than one user, but in my design a user can be associated with more than one company. So I have a separate class for CompanyUsers which looks as follows :-
public class CompanyUsers
{
public int Id { get; set; }
[Required]
public virtual Company Company { get; set; }
[Required]
public virtual ApplicationUser User { get; set; }
}
Now, when I register a user, I'm setting its role and also companies that the user belongs to, but seems like the UserManager defined in the built-in code has already saved it. So after adding CompanyUsers data, when I call applicationDbContext.Savechanges() it fails as the user has already been saved in the database. Can you tell me how I can achieve it? I can do it in some other logic, like after creating a user, in a separate function assign users to company(s), but I want to know the solution in this circumstances. Also I can redesign the user store.
My modified register function in AccountController is as follows :-
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email, Name = model.Name };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await UserManager.AddToRoleAsync(user.Id, model.Role);
var userCompany = new CompanyUsers
{
Company = _context.Companies.First(t => t.Id == model.CompanyId),
User = user
};
try
{
_context.CompanyUsers.Add(userCompany);
_context.SaveChanges();// throws exception
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
}
}
}
return RedirectToAction("UserViewAll", "Manage");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
I have just started mvc code first approach, so I may not understand if you use technical jargon, thanks In Advance for your help!!!!!
Upvotes: 0
Views: 199
Reputation: 41
Try adding the following code in the if (result.Succeeded)
block:
_context.Entry(user).State = EntityState.Unchanged;
The issue appears to be that the data context in this method does not know the state of the user
entity because UserManager.CreateAsync
uses a separate context. The entity is attached when you assign it to the CompanyUser
entity, and then this data context tries to save it as a new entity.
Upvotes: 1