c# 为什么我的抽象基本控制器中的User(如User.Identity.Name)为null?

更新时间:2024-01-26 下载TXT文档 下载Word文档

我当时在问一个相关的问题,但把标题弄乱了,没人能理解。由于我现在可以更精确地提出问题,因此我决定将其重新表述为一个新问题,然后关闭旧问题。抱歉

因此,我要做的是将数据(我的自定义用户的昵称存储在数据库中)传递给LoginUserControl。此登录名是通过Html.RenderPartial()从母版页呈现的,所以我真正需要做的是确保每个调用都存在ViewData [" UserNickname"]。但是我不想在每个控制器的每个动作中填充ViewData [" UserNickname"],所以我决定使用这种方法并创建一个抽象的基础控制器来为我完成工作,如下所示:

public abstract class ApplicationController : Controller
    {
        private IUserRepository _repUser;

        public ApplicationController()
        {
            _repUser = RepositoryFactory.getUserRepository();
            var loggedInUser = _repUser.FindById(User.Identity.Name); //Problem!
            ViewData["LoggedInUser"] = loggedInUser;
        }
    }

这样,无论我的派生控制器执行什么操作,用户信息都已经存在。

到目前为止,一切都很好。现在解决这个问题:

我无法调用User.Identity.Name,因为User已经为空。在我所有的派生控制器中并非如此,因此它特定于抽象基本控制器。

我在代码的另一个位置通过FormsAuthentication设置了User.Identity.Name,但是我认为这不是问题-afaik User.Identity.Name可以为null,但User本身不能为null。

在我看来,HttpContext不可用(因为还为null ;-),并且我在这里缺少一个简单而重要的要点。谁能给我一些提示吗?我真的很感激。

这个问题的答案实际上很简单。由于Raimond指出的原因,我无法在构造函数中执行代码,但可以在构造函数之外执行。

因此,我要做的是在基本控制器类中重写onActionExecuting()(我为其创建了一个自定义属性,但仅重写该方法也可以使用),然后从那里进行用户查找。

现在它可以按预期工作,并且我没有重复的代码。

在实例化Controller之后,才分配User属性,但是您可以使用以下方法从构造函数中进行早期访问:

System.Web.HttpContext.Current.User

我的猜测是Controller的基本构造函数没有填充User,但是只有稍后为Controller设置ControllerContext时才知道。您应该在有关MVC应用程序生命周期的文档中进行检查(此处可能会做,尽管它可能是过时的,因为它是用于预览版本的),或者只是检查MVC的源代码。

从我拥有的MVC(也是预览版,但应该没问题)的代码中:
(在控制器中)

 public IPrincipal User {
            get {
                return HttpContext == null ? null : HttpContext.User;
            }
        }

...

public HttpContextBase HttpContext {
        get {
            return ControllerContext == null ? null : ControllerContext.HttpContext;
        }
    }

我没有在代码中看到默认构造函数的实现。
那将证明在构造时ControllerContext为null。

因此,您应该在其他地方执行您的代码。 短码网 duanma.net

  • 奇怪,因为User为空,但System.Web.HttpContext.Current.User不是。 MVC 1.0

谢谢赖蒙德。我太累了,看不到明显的东西。
@Keeney:是的,上下文始终为空。赖蒙德指出了原因。还是谢谢你,我也没明白为什么:-)

我当前的工作解决方案(尽管不是我想要的)是一个属性,用于装饰所有控制器动作。这是实现:

public class MasterPageDataAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
            IUserRepository _repUser = RepositoryFactory.getUserRepository();
            IPrincipal siteUser = filterContext.Controller.ControllerContext.HttpContext.User;
            User loggedInUser = null;

            if (siteUser == null || siteUser.Identity.Name == null)
            {
                //do nothing
            }
            else
            {
                loggedInUser = _repUser.findUserById(siteUser.Identity.Name);
            }
            filterContext.Controller.ViewData["LoggedInUser"] = loggedInUser ?? new User { Nickname ="Guest" };
        }
    }

我将研究如何以遵循DRY原理的方式执行该代码,因为为此使用属性肯定意味着重复自己。也许某种拦截器(有趣的想法)或挂钩可能会有所帮助。

为此加油。

  • 我建议覆盖自定义Controller类的Initialize方法,并将代码从构造函数移到那里。

您可以使用类似以下内容的方法来抓住它吗:

HttpContext currentContext = HttpContext.Current;
string userName = currentContext.User.Identity.Name;

还是HttpContext总是空的?

您可以通过抽象类的构造函数设置httpContext吗?并以这种方式使用它?

我在basecontroller实现中执行此操作,它按预期工作。

public abstract class BaseController : Controller
{
    public bool LoggedOn
    {
        get { return User.Identity.IsAuthenticated; }
    }
}

这对我总是返回true或false,因此User != null

  • 这是因为在调用LoggedOn属性时,该User对象已被填充。
  • 因为属性获取器不是控制器构造函数

如果在构造函数中需要User,请注入IPrincipal

 // startup.cs
 // Inject IPrincipal
 services.AddTransient<IPrincipal>(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);

然后在构造函数中添加为IPrincipal。请注意,使用ASPNET保证它是ClaimsPrincipal-因为这就是HttpContext.User

类似问题

在MVC管道中从构造函数调用还为时过早。

将代码移至OnAuthorization,您将在参数中获得授权用户。为我工作!

从您的示例中,我将执行以下操作:

public abstract class ApplicationController : Controller {
    private IUserRepository _repUser;

    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        _repUser = RepositoryFactory.getUserRepository();
        var loggedInUser = _repUser.FindById(filterContext.HttpContext.User.Identity.Name); //Problem!
        ViewData["LoggedInUser"] = loggedInUser;
    }


}

到Masterfu:
我在您的帮助下做了一些类似的事情,希望对以后的访问者有所帮助。
就我而言,我需要为不同的用户创建控制器的仓库,但是在控制器的构造函数中,(主要)User尚未准备好。所以我为控制器创建了一个属性:

[CreateRepositoryByUser]
public class MFCController : Controller
{
    protected MFCRepository _repository
    {
        get { return ViewData["repository"] as MFCRepository; }
    }
...

_repository实际上不是控制器的私有变量,而是由该属性创建的:

public class CreateRepositoryByUser : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        CreateRepository(filterContext);
    }

    public static void CreateRepository(ActionExecutingContext filterContext)
    {
        if (filterContext.Controller.ViewData["repository"] == null)
        {
            filterContext.Controller.ViewData["repository"] =
                MFCRepository.CreateMFCRepository(filterContext.Controller.ControllerContext.HttpContext.User);
        }
    }
}

我将创建存储库的代码放在单独的方法中,以防其他属性可能要在触发此属性之前使用(主要)User。

以上就是短码网小编为大家整理的《c# 为什么我的抽象基本控制器中的User(如User.Identity.Name)为null?》相关内容,希望大家喜欢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若内容造成侵权/违法违规/事实不符,请将联系本站反馈,一经查实,立即处理!

c# 为什么我的抽象基本控制器中的User(如User.Identity.Name)为null?》文档下载仅供参考学习,下载后请在24小时内删除。

转载注明出处:https://www.duanma.net/article/d9bfb771023.html

回到顶部