... and we're only inside Microsoft.AspNet.Identity. (We're not even looking at the base implementation at Microsoft.AspNet.Identity.EntityFramework.)
The UserManager
class only takes in an IUserStore<TUser>
at constructor. It does not have an IUserRoleStore<TUserRole>
which I imagine would need to be accessed to determine whether UserManager.IsInRoleAsync(string, string)
or not.
I'm thinking UserStore's implementation would have an IsInRoleAsync(string, string)
function as well (then it would all make sense), but it does not.
Another strange thing - how can UserManager be able to perform password setting and resetting if all it knows inside its implementation is that we're dealing with an IUser
- with only string Id
and string UserName
as properties?
Alright, after much digging and lucky discovery - it turns out that Microsoft.AspNet.Identity.Core comes with a few other interfaces, in particular,
IUserRoleStore<TUser>
andIUserPasswordStore<TUser>
which both "inherit"(implement) IUserStore<TUser>.So if we wanted role management capabilities, we implement
IUserRoleStore<TUser>
:Now we can pass
MyUserStore
toUserManager<TUser>
, becauseMyUserStore
is anIUserRoleStore<TUser>
, which is anIUserStore<TUser>
:I suspect, then, that the source code for
UserManager<TUser>
uses reflection to find out whether the store passed into it at constructor implements one ofIUserStore<TUserStore>
's "child interfaces", in order to be able to perform role checks (if it implementsIUserRoleStore<TUser>
) or password set/reset (if it implementsIUserPasswordStore<TUser>
).I hope you find this useful because most documentation (MVC tutorials and such) don't tell us this detail. They tell us to use the
UserStore<TUser>
implementation of Microsoft.AspNet.Identity.EntityFramework - where all we have to do is pass in a customUser
object (that implementsIUser
) and we're good to go.