0

I have these extension methods below, 2 from ClaimsPrincipal and one from UserManager, all fetch email.

What is the difference and which one is faster? (i.e. doesn't require as much time to fetch from the database or doesn't fetch from the database at all or do they all fetch from the db?

var email = HttpContext.User.GetUserEmail();

public static string GetUserEmail(this ClaimsPrincipal user) {
  return user.FindFirst(ClaimTypes.Email)?.Value;
}

var email = HttpContext.User.RetrieveEmailFromPrincipal();

public static string RetrieveEmailFromPrincipal(this ClaimsPrincipal user) {
  return user?.Claims?.FirstOrDefault(x => x.Type == ClaimTypes.Email)?.Value;
}

var ca = await _userManager.Users
    .Where(p => p.Id == d)
    .Select(p => p.Email)
.FirstOrDefaultAsync();
Charlieface
  • 52,284
  • 6
  • 19
  • 43
chuckd
  • 13,460
  • 29
  • 152
  • 331

1 Answers1

2

GetUserEmail() and RetrieveEmailFromPrincipal() are extension methods for ClaimsPrincipal objects. They are retrieving the user's email address from the claims. If you check the implementation FindFirst() you will find that it uses the same foreach loop for iteration as FirstOrDefault(). The difference between the two is mostly stylistic and there is no significant difference in performance between them.

The time complexity of these two methods would be very similar. They both have to scan through the list of claims for the user until they find a claim of the required type.

The third approach retrieves the user's email address from the database using Entity Framework.

Usually, the extension methods on ClaimsPrincipal would be faster, because the claims are already in memory (retrieved during the authentication process) and there's no need to make a round trip to the database. However, they require that the email claim has already been added to the user's claims, which might not always be the case, depending on how your application is set up.

Please read the article for details about fetching user data How to get the current logged in user ID in ASP.NET Core?

Adalyat Nazirov
  • 1,611
  • 2
  • 14
  • 28
  • Hi Adalyat. Thanks for the info, and in my case I have added email to claims, so I will use the first method to fetch email, Id, username, etc. All different claims added when I authenticate/create token. – chuckd Jun 11 '23 at 08:23
  • Quick question - Do you know if there is a way to fetch roles for a user without using var roles = await _userManager.GetRolesAsync(user); where I have to pass in my User entity? I want to fetch my user roles by id or some singular value, not the entire User entity, as it's large. I can set up another post if you think that's necessary? – chuckd Jun 11 '23 at 08:24
  • As I'm aware there is no ready-to-use way to fetch ALL user roles. The common approach is `User.IsInRole("roleName")` that relies on claims too. If you need to fetch all user roles you can try `User.Identities.Select(s => s.FindFirst(s.RoleClaimType)?.Value);`. – Adalyat Nazirov Jun 11 '23 at 09:00
  • But I have to inform you that if you are going to manage roles in your app you still need to use `UserManager` and `RoleManager`. The methods above are suitable for read-only operations – Adalyat Nazirov Jun 11 '23 at 09:02
  • I'd like to make another post to explain what I'd like to do and it would be hard in the comments. Will you take a look when I post it? – chuckd Jun 11 '23 at 09:06
  • Hi Adalyat. Here is my post - https://stackoverflow.com/q/76449819/1186050 – chuckd Jun 11 '23 at 09:26
  • sure. could you accept the answer if you satisfied in this branch – Adalyat Nazirov Jun 11 '23 at 10:18