从局部视图中获取 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
希望对您有所帮助。
我问过有关旧 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
希望对您有所帮助。