I am working on an application which records users who registers to access some resources on web pages. I'm using ASP.NET MVC 5 with ASP.NET Identity. I use the same value for Email and for a UserName. I have a table which store webpages. I added also a WebpageId column to AspNetUsers table to identify a webpage. Actually, between AspNetUsers table and Webpage table there is many to many relationship, but for some reason I wanted to have multiple records for a user in AspNetUsers table – one for each webpage where the user is registered.
If a user with user@examplemail.com is registered to webpage1 it does not mean that he is registered to webpage2. When he registers to webpage2 with the same e-mail it should be actually completely invisible for him that he is already registered in the system as a user of webpage1.
In order to have multiple records with the same UserName in AspNetUsers table I removed a unique index on UserName and instead I created a unique index on two columns: UserName and WebpageId.
But when I try to register to webpage2 with the e-mail address that is already registered to webpage1, I get DbEntityValidationException with the following validation message : „Username user@examplemail.com has already been taken”. This is thrown in AccountControler.Register() method when UserManger is used to create a new user.
My first try to solve the problem was to customize the UserManager class. I created a subclass of UserManager where I overriden FindByEmailAsync and FindByNameAsync methods in a way that they look for a pair email+webpage or name+webpage:
var existingUser = this.db.Users
.FirstOrDefault(x => x.UserName == userName &&
x.WebpageId == webpageId);
return existingUser;
My second try was to additionally customize UserValidator of this UserManager. I do there something similar to the code above - try to get user with the same UserName and webpageId. When user is not found, I return IdentityResult.Success.
No success. Still having DbEntityValidationException with „Username user@examplemail.com has already been taken” validation error.
Any idea which ASP.NET Identity component still looks for a user with a user name (without checking the webpageId)? How should I customize ASP.NET Identity to handle such a scenario?
Here is a part of the exception callstack:
at System.Data.Entity.Internal.InternalContext.SaveChangesAsync(CancellationToken cancellationToken) at System.Data.Entity.Internal.LazyInternalContext.SaveChangesAsync(CancellationToken cancellationToken) at System.Data.Entity.DbContext.SaveChangesAsync(CancellationToken cancellationToken) at System.Data.Entity.DbContext.SaveChangesAsync() at Microsoft.AspNet.Identity.EntityFramework.UserStore
6.<SaveChanges>d__31.MoveNext() (...) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult() at UserRegistrationSystem.Web.Controllers.AccountController.d__11.MoveNext() in i:\Repo\RegistrationSystem\UserRegistrationSystem.Web\Controllers\AccountController.cs:line 126
FYI, I also asked the same question on ASP.NET Identity forum.
What you're describing sounds like multi-tenancy.
I've answered a related question here, and provided a library to implement it
https://github.com/JSkimming/AspNet.Identity.EntityFramework.Multitenant