User.GetUserId () does not work inside the controller controller

I get the following error: Value cannot be null. Parameter Name: main

How can I access Identity (userId) inside the controller constructor? I can make it work by wrapping an unsuccessful call in a function (both highlighted below).

Is there anything I need to enter?

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 } } 
+6
source share
2 answers

As @Henk noted, the controllerโ€™s constructor will be executed before the ActionContext is installed, so you will not have access to properties such as Context , Request or User . You need to get userId in the context of the request.

You can use the old-fashioned action filter approach, which is still part of the MVC6 pipeline (which also supports asynchronous action filters through IAsyncActionFilter ).

Since you want to set a property in your controller, the easiest way to implement this is to override the OnActionExecuting method in the controller class. This works because you inherit a Controller that already implements IActionFilter .

 public override void OnActionExecuting(ActionExecutingContext context) { //Get user id userId = User.GetUserId(); } 

Edit

If you check DefaultControllerFactory , you will see that:

  • the controller is first created.
  • then an ActionContext is set (via DefaultControllerPropertyActivator , which is one of the property activators):

     var controller = _controllerActivator.Create(actionContext, controllerType); foreach (var propertyActivator in _propertyActivators) { propertyActivator.Activate(actionContext, controller); } 
+6
source

When you create an instance of the controller, there is no guarantee that the request information is available in the HttpContext. Perhaps there will be no request. Is there a reason why you need this information in the constructor?

Edit
I understand your problem. What I usually do in a similar scenario is to create a property using a support field that asks only once for each controller:

 private int? _userId; public int UserId { get { if (!_userId.HasValue) { // query from db. _userId = 42; } return _userId.Value; } } 
+1
source

All Articles