2

I have asked similar question about older MVC version and Membership, but those solutions don't work with Idendity and MVC 6.
I want to display user's first name inside _LoginPartial.cshtml file. So, instead of "Hello " + User.Identity.GetUserName() + "!" I want to access ApplicationUser.FirstName for the currently logged in user. What is the best way to do this?

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
Sergi0
  • 1,084
  • 14
  • 28

4 Answers4

3

I present a solution in my opinion better because it requires only one search for profile per request.

First: Create a user service

public interface IUserProfileLoader
{
    Task<ApplicationUser> GetCurrentApplicationUser(ClaimsPrincipal user);
}

public class UserServices : IUserProfileLoader
{
    private readonly UserManager<ApplicationUser> _userManager;
    private ApplicationUser _CurrentUser;
    public UserServices([FromServices]UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }
    public async Task<ApplicationUser> GetCurrentApplicationUser(ClaimsPrincipal user)
    {
        if (_CurrentUser == null)
        {
            _CurrentUser = await _userManager.FindByIdAsync(user.GetUserId());
        }
        return _CurrentUser;
    }
}

Then register the service

In ConfigureServices add the following:

// Add user profile services.
services.AddScoped<IUserProfileLoader, UserServices>();

For use in a View

Inject the service:

@inject IUserProfileLoader UserServices

then access property like this:

@((await UserServices.GetCurrentApplicationUser(User)).Email)

For use elsewhere...

You can access the service in an Action (for example) using:

[FromServices]IUserProfileLoader UserServices

I hope this helps.

gidanmx2
  • 469
  • 1
  • 9
  • 24
2

For a much simpler fix, you can inject services directly into your view to retrieve the ApplicationUser.

@inject UserManager<ApplicationUser> MyManager

@{
    var applicationUser = MyManager.FindByIdAsync(User.Identity.GetUserId());
}

Also note you can add the @inject in your _ViewStart.cshtml if you want access to your UserManager<ApplicationUser> from all of your views.

N. Taylor Mullen
  • 18,061
  • 6
  • 49
  • 72
0

I've implemented this solution using components, but it seems like an overkill.

Views\Shared_LoginPartial.cshtml

...
@await Component.InvokeAsync("FirstName", User.Identity.GetUserId())
...


Views\Shared\Components\FirstName\Default.cshtml

@model Models.ApplicationUser

@Html.ActionLink("Hello " + Model.FirstName + "!", "Manage", "Account", routeValues: null, htmlAttributes: new { title = "Manage" })


ViewComponents\FirstNameViewComponent.cs

public class FirstNameViewComponent : ViewComponent
{
    private readonly IUserService m_userService;

    public FirstNameViewComponent(IUserService userService)
    {
        m_userService = userService;
    }

    public async Task<IViewComponentResult> InvokeAsync(string userId)
    {
        Models.ApplicationUser user = await m_userService.FindUserByIdAsync(userId);
        return View(user);
    }
}


Services\UserService.cs

public interface IUserService
{
    Task<ApplicationUser> FindUserByIdAsync(string id);
}

public class UserService : IUserService
{
    private readonly UserManager<ApplicationUser> m_userManager;

    public UserService(UserManager<ApplicationUser> userManager)
    {
        m_userManager = userManager;
    }

    public Task<ApplicationUser> FindUserByIdAsync(string id)
    {
        return m_userManager.FindByIdAsync(id);
    }
}


Startup.cs

...
services.AddScoped<IUserService, UserService>();
...


I guess I can update the user service and store ApplicationUser after log in, and removed it after log off, but I wonder if there is another way to solve this. Also I'm not sure if scoped service is the best here, I didn't find a way to make it session, not request scoped.

Sergi0
  • 1,084
  • 14
  • 28
0

I have found another solution, implementing custom IPrincipal. I think it's the best, cause it doesn't require user search every time I need that info.

Community
  • 1
  • 1
Sergi0
  • 1,084
  • 14
  • 28