简体   繁体   中英

Value cannot be null. (Parameter 'principal') [ Identity ] [ ASP.net core ]

I'm working on an Asp.Net core project, and I use Identity framework.

Problem:

Inside a Controller I try to get the current user information based on User (his type is ClaimsPrincipal ) but I got a runtime error.

What I try:

That is my Controller code

[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")
               };
    }


}

Where I got the error?

The error happened in SetCurrentUser method, Visual Studio thrown this exception:

System.ArgumentNullException: 'Value cannot be null. (Parameter 'principal')'

Error screenshot:

截屏

Additional info:

My project depends on .Net 5

Please any help to fix this issue?

The User and HttpContext are not set yet (still null ) in the controller's constructor. If you want to access it, try injecting the IHttpContextAccessor into the constructor like this:

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
    //...
}

However that way is not every standard especially when you need to call async methods in the constructor, which should not be done at all. Your methods are even declared using async void which should be absolutely avoided. Actually what you want is automatically make some info available before the action being executed . That's the perfect fit for an IActionFilter or IAsyncActionFilter (here using the async filter is better because you're going to call async methods in there). Because the info made available right in the controller (as properties/fields) so it will be more convenient to override the OnActionExecutionAsync method of the controller instead of using the filters I've mentioned. Using the filters in this case may require you to share the info around (such as via HttpContext.Items or request feature...) which is a bit inconvenient.

Here's how you should do it:

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() { ... }

That's all, remember to remove your equivalent code in the constructor.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM