MVC5 Account Controller null reference exception

落爺英雄遲暮 提交于 2019-11-30 14:03:13

问题


I am trying to implement user roles into my MVC web application. However I am getting a null exception on the line return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>(); in my account controller.

Account Controller

[Authorize]
public class AccountController : Controller
{
    private ApplicationSignInManager _signInManager;
    private ApplicationUserManager _userManager;
    private ApplicationRoleManager _roleManager; 

    public AccountController(){}

    public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager, ApplicationRoleManager roleManager)
    {   UserManager = userManager;
        SignInManager = signInManager;
        RoleManager = roleManager; }
    public ApplicationRoleManager RoleManager
    {
        get { return _roleManager ?? HttpContext.GetOwinContext().Get<ApplicationRoleManager>(); }
        private set { _roleManager = value; }
    }

    public ApplicationSignInManager SignInManager
    {
        get { return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>(); }
        private set  { _signInManager = value; }
    }

    public ApplicationUserManager UserManager
    {
        get { return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>(); }
        private set {_userManager = value; }
    }

ActionResult that will trigger the adding of the user to the role.

    [System.Web.Mvc.HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult RoleAddToUser(string UserName, string RoleName)
    {
        ApplicationUser user = context.Users.FirstOrDefault(u => u.UserName.Equals(UserName, StringComparison.CurrentCultureIgnoreCase));
        var account = new AccountController();
        if (user != null) account.UserManager.AddToRole(user.Id, RoleName);
        var list = context.Roles.OrderBy(r => r.Name).ToList().Select(rr => new SelectListItem { Value = rr.Name.ToString(), Text = rr.Name }).ToList();
        ViewBag.Roles = list;
        return View("ManageUserRoles");
    }

Startup.Auth does contain

        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

Identity Config

    // Configure the application sign-in manager which is used in this application.
public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
    public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager)
        : base(userManager, authenticationManager)
    {
    }

    public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
    { return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager); }

    public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
    { return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication); }
}
public class ApplicationRoleManager : RoleManager<IdentityRole>
{
    public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore)
        : base(roleStore) { }

    public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
    {
        return new ApplicationRoleManager(new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()));
    }
}

Where is the null reference coming from? In the code I am double checking that the user exists.

Thanks


回答1:


These are undoubtedly the offending lines...

var account = new AccountController();
if (user != null) account.UserManager.AddToRole(user.Id, RoleName);

Controllers aren't meant to be instantiated in this way because they are heavily tied to the current HTTP request (thus the HttpContext).

When HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>(); gets hit, HttpContext is null because there is no context.

You can simply put the same property in your controller where you are trying to access the UserManager. This works because the OwinContext is shared across your entire application.

public class HomeController : Controller
{
    public ApplicationUserManager UserManager
    {
        get { return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>(); }
        private set {_userManager = value; }
    }

    public ActionResult RoleAddToUser(string UserName, string RoleName)
    {
        ApplicationUser user = context.Users.FirstOrDefault(u => u.UserName.Equals(UserName, StringComparison.CurrentCultureIgnoreCase));
        if (user != null) UserManager.AddToRole(user.Id, RoleName);

        //Other code...

        return View("ManageUserRoles");
    }
}

And if you want to get really fancy, declare a BaseController that inherits from Controller, put the UserManager property inside, and have all your other controllers inherit from your base.



来源:https://stackoverflow.com/questions/27750918/mvc5-account-controller-null-reference-exception

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!