带有ASP.NET MVC的HttpContext.Items

Rya*_*man 33 asp.net-mvc httpcontext

我正在使用单例模式我自己的ApplicationContext类.我想将它的实例存储在HttpContext.Items中,因为它可以在请求的所有部分中访问.我一直在阅读将HttpContext与ASP.NET MVC一起使用,其中一个主要问题是它引入了测试复杂性.我已经尝试过对HttpContext.Items的可测试性进行研究,但我能找到的就是Session上的内容.我发现的唯一一件事是在Wrox上的Professional ASP.NET 3.5 MVC书中的一个示例章节(这里是pdf链接).在第15页,它说:

你不能使用的东西:HttpContext.Items
在本节的上面,我们来了,告诉你我们骗了你:ASP.NET MVC和ASP.NET Web Forms之间没有共享HttpContext.因此,您无法使用HttpContext.Items集合来存储和检索数据位.

这是因为一旦你重定向到一个Controller,你的HttpHandler就变成了System.Web.Mvc.MvcHandler,它是使用HttpContextWrapper创建的,它将有自己的HttpContext.Current定义.不幸的是,在此握手期间,HttpContext.Items之类的东西不会被传输.

这归结为HttpContext类型,尽管看起来和听起来非常相似,但是不一样,并且你不能以这种方式传递数据.

现在,我已经尝试过对此进行测试,据我所知,如果使用RedirectToAction重定向到另一个控制器,HttpContext.Items仍会保留.我正在使用默认的ASP.NET MVC项目来测试它.我所做的是,将此方法添加到Global.asax.cs:

protected void Application_BeginRequest()
{
    Context.Items["Test"] = "Hello World";
}
Run Code Online (Sandbox Code Playgroud)

在HomeController.cs中,我将Index方法更改为:

public ActionResult Index()
{
    return RedirectToAction("About");
}
Run Code Online (Sandbox Code Playgroud)

并将About方法更改为:

public ActionResult About()
{
    Response.Write(Convert.ToString(HttpContext.Items["Test"]));
    return View();
}
Run Code Online (Sandbox Code Playgroud)

当我运行应用程序时,页面正确地重定向到/ Home/About和Response.Writes在global.asax.cs中设置正确的"Hello World"字符串.

所以,在我看来,当他们说"像HttpContext.Items这样的东西没有转移"时,我或者不理解这本书是什么意思,或者它确实转移了这些东西,并且可以使用HttpContext.Items.

如果你们建议我避免使用HttpContext.Items,是否有另一种方法可以在每个请求的基础上跨请求存储对象?

Nic*_*arr 38

你的问题是问一些事情,但我认为第1项是你正在寻找的答案.

  1. Context.Items在每个请求的基础上用于缓存是否可以?是.如果正在处理中,每个请求,Web场中的每台计算机都是您的标准,那么Context.Items会为您提供该标准.

  2. Context.Items很难测试?至于可测试性,我会隐藏Context.Items在某种界面后面.这样您就可以获得单元测试功能而无需Context.Items直接引用.否则,你需要测试什么Context.Items?框架将存储和检索值?保持你的代码无知,System.Web你将是一个快乐的露营者.

  3. Context.Items活下来RedirectToAction吗?不,您的测试无效.它在每个Web请求上设置"Hello,world",并且您的测试跨越了两个Web请求.第一个是调用Index操作的时候.第二个是RedirectToAction调用动作时(它是HTTP 302).要使其失败,请在"索引"操作中设置一个新值,并查看它是否保留在"关于"操作中.