从局部视图中获取 ApplicationUser

Get ApplicationUser from Partial View

我问过有关旧 MVC 版本和成员资格的类似问题,但这些解决方案不适用于 Idendity 和 MVC 6。
我想在 _LoginPartial.cshtml 文件中显示用户的名字。因此,我想访问当前登录用户的 ApplicationUser.FirstName 而不是 "Hello " + User.Identity.GetUserName() + "!"。执行此操作的最佳方法是什么?

我已经使用组件实现了这个解决方案,但它似乎有点矫枉过正。

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>();
...


我想我可以在登录后更新用户服务并存储 ApplicationUser,并在注销后将其删除,但我想知道是否有另一种方法可以解决这个问题。另外我不确定这里的范围服务是否最好,我没有找到一种方法让它成为会话,而不是请求范围。

对于更简单的修复,您可以将服务直接注入视图以检索 ApplicationUser

@inject UserManager<ApplicationUser> MyManager

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

另请注意,如果您想从所有视图中访问您的 UserManager<ApplicationUser>,您可以在 _ViewStart.cshtml 中添加 @inject

我找到了另一个解决方案,implementing custom IPrincipal。我认为这是最好的,因为它不需要每次我需要该信息时都需要用户搜索。

我提出一个我认为更好的解决方案,因为每个请求只需要搜索一次配置文件。

首先:创建用户服务

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;
    }
}

然后注册服务

ConfigureServices 中添加以下内容:

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

用于视图

注入服务:

@inject IUserProfileLoader UserServices

然后像这样访问 属性:

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

用于其他地方...

您可以在 Action 中访问该服务(例如)使用:

[FromServices]IUserProfileLoader UserServices

希望对您有所帮助。