值不能为空。 (参数'principal')[身份][ASP.net核心]
Value cannot be null. (Parameter 'principal') [ Identity ] [ ASP.net core ]
我正在做一个 Asp.Net core
项目,我使用 Identity
框架。
问题:
在Controller中我尝试根据User
获取当前用户信息(他的类型是ClaimsPrincipal
)但是我得到一个运行时错误。
我的尝试:
那是我的 Controller
代码
[Authorize]
public class ServiceController : Controller
{
private readonly UserManager<AppUser> _userManager;
private RoleManager<IdentityRole> _roleManager;
private AppUser _currentUser;
private AppRoles _currentUserRole;
public ServiceController(UserManager<AppUser> userManager, RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
_roleManager = roleManager;
SetCurrentUser();
SetCurrentUserRole();
}
#region Private Methods
private async void SetCurrentUser()
{
var us = User;
_currentUser = await _userManager.GetUserAsync(User);
}
private async void SetCurrentUserRole()
{
string currentUserRoleName = _userManager.GetRolesAsync(_currentUser).Result.FirstOrDefault();
if (User.IsInRole(AppRoles.Admin.ToString()))
{
_currentUserRole = AppRoles.Admin;
}
else if (User.IsInRole(AppRoles.User.ToString()))
{
_currentUserRole = AppRoles.User;
}
}
#endregion
public ActionResult Get()
{
return _currentUserRole switch
{
AppRoles.User => RedirectToAction("Services", "User"),
AppRoles.Admin => RedirectToAction("Services", "Admin"),
_ => RedirectToPage("Login")
};
}
}
哪里出错了?
错误发生在SetCurrentUser
方法中,Visual Studio抛出了这个异常:
System.ArgumentNullException: 'Value cannot be null. (Parameter
'principal')'
错误截图:
附加信息:
我的项目依赖于.Net 5
请帮忙解决这个问题?
User
和 HttpContext
尚未在控制器的构造函数中设置(仍然是 null
)。如果您想访问它,请尝试将 IHttpContextAccessor
注入构造函数,如下所示:
public ServiceController(UserManager<AppUser> userManager,
RoleManager<IdentityRole> roleManager,
IHttpContextAccessor httpContextAccessor){
var user = httpContextAccessor.HttpContext.User;
//now pass the user above around to use it instead of basing on the property User
//...
}
然而,这种方式并不是每个标准,尤其是当您需要在构造函数中调用 async
方法时,根本不应该这样做。您的方法甚至使用 async void
声明,这应该绝对避免。实际上,您想要的是在执行操作之前自动提供一些信息。这非常适合 IActionFilter
或 IAsyncActionFilter
(这里使用异步过滤器更好,因为您将在其中调用异步方法)。因为信息在控制器中可用(如 properties/fields),所以覆盖控制器的 OnActionExecutionAsync
方法而不是使用我提到的过滤器会更方便。在这种情况下使用过滤器可能需要您共享信息(例如通过 HttpContext.Items
或请求功能...),这有点不方便。
以下是您应该如何操作:
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
await SetCurrentUserAsync();
await SetCurrentUserRoleAsync();
await base.OnActionExecutionAsync(context, next);
}
//adjust your methods
private async Task SetCurrentUserAsync() { ... }
private async Task SetCurrentUserRoleAsync() { ... }
就是这样,记得删除构造函数中的等效代码。
我正在做一个 Asp.Net core
项目,我使用 Identity
框架。
问题:
在Controller中我尝试根据User
获取当前用户信息(他的类型是ClaimsPrincipal
)但是我得到一个运行时错误。
我的尝试:
那是我的 Controller
代码
[Authorize]
public class ServiceController : Controller
{
private readonly UserManager<AppUser> _userManager;
private RoleManager<IdentityRole> _roleManager;
private AppUser _currentUser;
private AppRoles _currentUserRole;
public ServiceController(UserManager<AppUser> userManager, RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
_roleManager = roleManager;
SetCurrentUser();
SetCurrentUserRole();
}
#region Private Methods
private async void SetCurrentUser()
{
var us = User;
_currentUser = await _userManager.GetUserAsync(User);
}
private async void SetCurrentUserRole()
{
string currentUserRoleName = _userManager.GetRolesAsync(_currentUser).Result.FirstOrDefault();
if (User.IsInRole(AppRoles.Admin.ToString()))
{
_currentUserRole = AppRoles.Admin;
}
else if (User.IsInRole(AppRoles.User.ToString()))
{
_currentUserRole = AppRoles.User;
}
}
#endregion
public ActionResult Get()
{
return _currentUserRole switch
{
AppRoles.User => RedirectToAction("Services", "User"),
AppRoles.Admin => RedirectToAction("Services", "Admin"),
_ => RedirectToPage("Login")
};
}
}
哪里出错了?
错误发生在SetCurrentUser
方法中,Visual Studio抛出了这个异常:
System.ArgumentNullException: 'Value cannot be null. (Parameter 'principal')'
错误截图:
附加信息:
我的项目依赖于.Net 5
请帮忙解决这个问题?
User
和 HttpContext
尚未在控制器的构造函数中设置(仍然是 null
)。如果您想访问它,请尝试将 IHttpContextAccessor
注入构造函数,如下所示:
public ServiceController(UserManager<AppUser> userManager,
RoleManager<IdentityRole> roleManager,
IHttpContextAccessor httpContextAccessor){
var user = httpContextAccessor.HttpContext.User;
//now pass the user above around to use it instead of basing on the property User
//...
}
然而,这种方式并不是每个标准,尤其是当您需要在构造函数中调用 async
方法时,根本不应该这样做。您的方法甚至使用 async void
声明,这应该绝对避免。实际上,您想要的是在执行操作之前自动提供一些信息。这非常适合 IActionFilter
或 IAsyncActionFilter
(这里使用异步过滤器更好,因为您将在其中调用异步方法)。因为信息在控制器中可用(如 properties/fields),所以覆盖控制器的 OnActionExecutionAsync
方法而不是使用我提到的过滤器会更方便。在这种情况下使用过滤器可能需要您共享信息(例如通过 HttpContext.Items
或请求功能...),这有点不方便。
以下是您应该如何操作:
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
await SetCurrentUserAsync();
await SetCurrentUserRoleAsync();
await base.OnActionExecutionAsync(context, next);
}
//adjust your methods
private async Task SetCurrentUserAsync() { ... }
private async Task SetCurrentUserRoleAsync() { ... }
就是这样,记得删除构造函数中的等效代码。