User.GetUserId() 在控制器的构造函数中失败
User.GetUserId() fails inside controller's constructor
我收到以下错误:值不能为空。参数名称:principal
如何在控制器的构造函数中访问身份 (userId)?我只能通过将失败的调用包装在一个函数中来让它工作(都在下面突出显示)。
有什么需要注射的吗?
public class BaseController : Controller {
protected readonly MylDbContext dbContext;
protected readonly string userId;
public BaseController(MylDbContext dbContext) {
this.dbContext = dbContext;
userId = User.GetUserId(); // fails here
}
public string GetUserId() {
return User.GetUserId(); // works here
}
}
实例化控制器时,无法保证请求信息在 HttpContext 中可用。可能根本没有请求。为什么在构造函数中需要该信息?
编辑
我明白你的问题。在这种情况下,我通常做的是创建一个 属性 和一个支持字段,每个控制器只查询一次:
private int? _userId;
public int UserId
{
get
{
if (!_userId.HasValue)
{
// query from db.
_userId = 42;
}
return _userId.Value;
}
}
如@Henk 所述,控制器构造函数将在设置 ActionContext 之前执行,因此您将无法访问 Context
、Request
或 User
等属性.您需要在请求的上下文中检索 userId。
您可以使用 action filters 的老式方法,它仍然是 MVC6 管道的一部分(它还通过 IAsyncActionFilter
支持异步操作过滤器)。
由于您想在控制器中设置 属性,实现此操作的最简单方法是重写控制器 class 中的 OnActionExecuting
方法。这是可行的,因为您继承自 Controller
,它已经实现了 IActionFilter
.
public override void OnActionExecuting(ActionExecutingContext context)
{
//Get user id
userId = User.GetUserId();
}
编辑
如果您检查 DefaultControllerFactory
,您会看到:
- 首先创建控制器
然后设置 ActionContext(通过 DefaultControllerPropertyActivator
,它是 属性 激活器之一):
var controller = _controllerActivator.Create(actionContext, controllerType);
foreach (var propertyActivator in _propertyActivators)
{
propertyActivator.Activate(actionContext, controller);
}
我收到以下错误:值不能为空。参数名称:principal
如何在控制器的构造函数中访问身份 (userId)?我只能通过将失败的调用包装在一个函数中来让它工作(都在下面突出显示)。
有什么需要注射的吗?
public class BaseController : Controller {
protected readonly MylDbContext dbContext;
protected readonly string userId;
public BaseController(MylDbContext dbContext) {
this.dbContext = dbContext;
userId = User.GetUserId(); // fails here
}
public string GetUserId() {
return User.GetUserId(); // works here
}
}
实例化控制器时,无法保证请求信息在 HttpContext 中可用。可能根本没有请求。为什么在构造函数中需要该信息?
编辑
我明白你的问题。在这种情况下,我通常做的是创建一个 属性 和一个支持字段,每个控制器只查询一次:
private int? _userId;
public int UserId
{
get
{
if (!_userId.HasValue)
{
// query from db.
_userId = 42;
}
return _userId.Value;
}
}
如@Henk 所述,控制器构造函数将在设置 ActionContext 之前执行,因此您将无法访问 Context
、Request
或 User
等属性.您需要在请求的上下文中检索 userId。
您可以使用 action filters 的老式方法,它仍然是 MVC6 管道的一部分(它还通过 IAsyncActionFilter
支持异步操作过滤器)。
由于您想在控制器中设置 属性,实现此操作的最简单方法是重写控制器 class 中的 OnActionExecuting
方法。这是可行的,因为您继承自 Controller
,它已经实现了 IActionFilter
.
public override void OnActionExecuting(ActionExecutingContext context)
{
//Get user id
userId = User.GetUserId();
}
编辑
如果您检查 DefaultControllerFactory
,您会看到:
- 首先创建控制器
然后设置 ActionContext(通过
DefaultControllerPropertyActivator
,它是 属性 激活器之一):var controller = _controllerActivator.Create(actionContext, controllerType); foreach (var propertyActivator in _propertyActivators) { propertyActivator.Activate(actionContext, controller); }