What is the difference between using user.Email
vs await _userManager.GetEmailAsync(user)
?
I mean, once I have the user instance itself, what is the use of the _userManager
's GetEmailAsync()
method which takes exactly that user instance as parameter? I can access the user's email via its property.
I examined the source and I do understand that there is an abstraction layer of using IUserEmailStore
but its default implementation is just returning the Email property...
I also do understand, that may exist other implementations, of IUserEmailStore
but this case the question will arise: are the user.Email
property and _userManager.GetEmailAsync(user)
consistent to each other, or are not?
If not, that is a problem, if yes, then we are returned to the original question: what is the use case of using _userManager.GetEmailAsync(user)?
(the same question goes to UserName, PhoneNumber, etc properties)
CodePudding user response:
What is the difference between using
user.Email
vsawait UserManager.GetEmailAsync(user)
?
user.Email
only works if yourTUser
actually has anEmail
property in the first place.- Fun-fact: ASP.NET-Core-Identity does not actually require whatever
class
you're using for yourTUser
to have aString Email
property.- i.e. what you're presupposing (that users have e-mail addresses) is not actually guaranteed in, nor required by, ASP.NET-Core-Identity.
- ASP.NET-Core-Identity's only constraint on
TUser
isTUser : class
, so you could even useString
orIDictionary
for yourTUser
if you're brave enough.- While ASP.NET-Core-Identity does have a
String Email { get; }
property defined only onclass Microsoft.AspNetCore.Identity.IdentityUser<TKey>
, but you are not obligated to use this class at all: it's just a prewritten implemention that covers the most common use-cases and (probably) saves most people time by having them subclass it.
- While ASP.NET-Core-Identity does have a
- Fun-fact: ASP.NET-Core-Identity does not actually require whatever
But there are also other scenarios to consider:
- ...such as domain-model design where users have multiple e-mail addresses per user, in which case having a single scalar
String Email { get; }
property simply won't work... though neither wouldGetEmailAsync
either, but that's another part of ASP.NET-Core-Identity's design that you missed: you can implementIUserStore<TUser>
and not implementIUserEmailStore<TUser>
, so there wouldn't be either anEmail
property nor aGetEmailAsync
method. (Just make sure you don't subclassclass UserStoreBase
) and instead build your store implementation from scratch.- In this hypothetical case, where no types implement
IUserEmailStore<TUser>
, there wouldn't be any methods anywhere in your codebase that would have to throwNotImplementedException
orNotSupportedException
. And that's a good thing: a common mantra when designing a domain-model is to "make invalid things impossible" (that's my corruption of the original maxim "make invalid state unrepresentable").
- In this hypothetical case, where no types implement
- ...such as domain-model design where users have multiple e-mail addresses per user, in which case having a single scalar
Another scenario is some (atypical, I'll admit) system where Users do have an email address, but it's not stored or represented by the in-memory
User
object, in which case you would have to use a custom implementation ofGetEmailAsync
to get a user's email address every time.- I imagine this might be a possibility when using a back-end user-store with extremely fine-grained security (e.g. some paranoid Active Directory setup where the current
Thread
's NT security token is used to attest permission to request e-mail addresses from the directory... but that idea is just speculation and I hope no-one ever actually has to support that, at least not without good blood-pressure medication on-hand).
- I imagine this might be a possibility when using a back-end user-store with extremely fine-grained security (e.g. some paranoid Active Directory setup where the current
In conclusion: Not every system has user e-mail addresses, and ASP.NET Core Identity doesn't require them to expose them - and the (admittingly very complicated) design of ASP.NET Core Identity reflects that.