簡體   English   中英

值不能是 null。 (參數“主體”)[身份][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: '值不能是 null。 (參數'主要')'

錯誤截圖:

截屏

附加信息:

我的項目依賴於.Net 5

請幫助解決這個問題?

UserHttpContext尚未在控制器的構造函數中設置(仍然是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聲明,這應該絕對避免。 實際上,您想要的是在執行操作之前自動提供一些信息。 這非常適合IActionFilterIAsyncActionFilter (這里使用異步過濾器更好,因為您將在那里調用異步方法)。 因為在 controller 中提供了信息(作為屬性/字段),所以覆蓋 controller 的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() { ... }

就是這樣,記住在構造函數中刪除你的等效代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM