简体   繁体   中英

Architecture and ASP.Net Identity

Im currently following the following GitHub for guidance on storing user data from ASP.Net Identity into Mongo: https://github.com/g0t4/aspnet-identity-mongo . With a basic proof of concept, I have been able to successfully store user data. The current issue that I am facing is my application requires two types of users (both will be stored to the same Mongo collection).

For simplicity, we can call the users A and B. Both A and B are setup as models and have their own properties. My initial idea was to setup both A and B as derived classes of ApplicationUser (see the IdentityModels.cs file in the referenced repo).

Registration into my application worked perfectly with this architecture and JSON documents were posted/stored into my MongoDB. The issue is when I try to login. Upon posting, I get the server error:

Element does not match any field or property of class Models.ApplicationUser

The error goes away when I put all of model A's elements into ApplicationUser; however, this leaves the issue of model B not being accounted for. As such, I wanted to ask what the best path would be for me to take with this? Some ideas I was batting around involved creating two unique UserManagers, using one large JSON document with all elements (seems kinda unorganized), or perhaps using one UserManager with an adapter for the two models?

The way you've set this up is fine, and the way it should be. The problem seems to be in how Mongo handles the inheritance, although you'd still have a different but equally problematic issue with something like SQL Server.

In short, what seems to be happening here is that you're essentially upcasting UserA / UserB to ApplicationUser , but since the JSON includes properties from those derived classes, which ApplicationUser doesn't, Mongo is choking on it. The solution is to use multiple UserManager s. It's a generic type that takes a TUser type param. The default implementation is UserManager<ApplicationUser> , but that assumes everything is an ApplicationUser . If you have derived user types, then you need to use type-specific UserManager<TUser> instances for those, ie UserManager<UserA> and UserManager<UserB> .

FWIW, the problem you'd experience with another data store is that the type that is saved is what determines the value of the Discriminator column added to instantiate the right type with queries. Even if you're creating UserA , for example, if you use an instance of UserManager<ApplicationUser> , it will be upcast to ApplicationUser and saved as ApplicationUser , not UserA . This is similar to what's happening in your Mongo setup, but something like SQL Server would accept it happily (although your data would then be messed up), whereas Mongo is erroring out.

Long and short, always use a UserManager<TUser> instance that's specific to the user type you're working with.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM