【问题标题】:Accessing Request.Cookies from a Controller Constructor从控制器构造函数访问 Request.Cookies
【发布时间】:2010-11-03 13:52:26
【问题描述】:

我正在使用 FormsAuthenticationTicket 的 UserData 属性来存储一些用户特定的信息。我有一个 HelperClass 将这个 UserData 反序列化为一个自定义对象以进行强类型访问。我的控制器设置如下

public class SomeController : Controller
{
    private CookieData _cookieData;

    public SomeController()
    {
        _service = new ForderungsStellerService(new ModelStateWrapper(this.ModelState));
        HttpCookie cookie = Request.Cookies[FormsAuthentication.FormsCookieName];
        FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
        _cookieData= GetSessionData.FromCookie(ticket);
    }
}

问题似乎是,请求在控制器构建时为空。当从 ActionMethod 访问 Request.Cookies 时,这个 sn-p 正在工作。

出于 DRY 的原因,我希望在构造函数中填充 _cookieData 对象。

有人对这个问题有提示吗?

最好的问候...

【问题讨论】:

    标签: asp.net asp.net-mvc cookies


    【解决方案1】:

    我将创建一个 ModelBinder,它可以理解 CookieData 以及如何从 Request 对象中获取它。我担心使构造函数满意所必需的单元测试创​​建代码。如果您将其作为具有模型绑定器的控制器的参数,您可以避免测试开销。

    public class SomeController : Controller
    {
      // only need to pass in the data object for unit testing.
      // ModelBinder takes care of DRY
      public ActionResult Index(CookieData cookieData)
      {
      }
    }
    

    为什么它在构造函数中不起作用的答案是,此时控制器尚未使用 ControllerContext 初始化。

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

    如果您真的想在构造函数中执行此操作(不要),请使用 HttpContext.Request 而不是包装器。但是这样做会使您的代码无法测试,并且对齐会下降 3 个点。

    【讨论】:

      【解决方案2】:

      DRY 很好,但在 ASP.NET MVC 的情况下,它通常意味着使用自定义过滤器属性或类似 talljoe 显示的模型绑定器。

          public override void OnActionExecuting(ActionExecutingContext filterContext)
           {
               HttpCookie cookie = filterContext.HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
              FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
              filterContext.ActionParameters["CookieData"] = GetSessionData.FromCookie(ticket);
      
      
               base.OnActionExecuting(filterContext);
           }
      

      【讨论】:

        【解决方案3】:

        重写 Controller.Initialize():

        protected override void Initialize(RequestContext requestContext) {
          base.Initialize(requestContext);
          // do further initialization here
        }
        

        在调用 base.Initialize() 后,您可以使用 Request 等属性。

        【讨论】:

        • 也是一个正确的解决方案。会工作,但会使单元测试更难。
        • 戈登说得对。更喜欢使用 Talljoe 的解决方案来获得更松散耦合且更易于测试的问题解决方案。
        猜你喜欢
        • 1970-01-01
        • 2016-02-07
        • 1970-01-01
        • 1970-01-01
        • 2018-05-25
        • 1970-01-01
        • 2017-05-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多