从控制器构造函数访问Request.Cookies

4

我正在使用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);
    }
}

问题似乎是,在控制器构建时,Request为空。当从ActionMethod访问Request.Cookies时,此代码段有效。

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

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

最好的问候...

3个回答

6
我会创建一个ModelBinder,它能够理解CookieData并从请求对象中获取它。我担心为了让构造函数顺利通过而需要编写的单元测试代码。如果你将其作为控制器的参数与Model Binder一起使用,就可以避免这种测试开销。
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)
  {
  }
}

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

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

如果你真的想在构造函数中这么做(不建议),那么请使用HttpContext.Request而不是包装类。但这样做会使你的代码难以测试,且可读性将降低3分。


6

重写Controller.Initialize():

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

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

也是一种正确的解决方案。可以工作,但会使单元测试变得更加困难,这不应该是这样的。 - Gordon
戈登是正确的。更倾向于使用Talljoe的解决方案,因为它可以提供更松散耦合和更易于测试的解决方案来解决这个问题。 - Carl Heinrich Hancke

0

保持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);
     }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接