我正在使用单例模式我自己的ApplicationContext类。我想将它的实例存储在HttpContext.Items中,因为它可以在请求的所有部分中访问。我一直在阅读将HttpContext与ASP.NET MVC一起使用,其中一个主要问题是它引入了测试复杂性。我已经尝试过对HttpContext.Items的可测试性进行研究,但我能找到的就是Session上的内容。我发现的唯一一件事是在Wrox(pdf link here)上的Professional ASP.NET 3.5 MVC书中的示例章节之外。在第15页,它说:
你不能使用的东西:HttpContext.Items
在本节的上方,我们清理过来并告诉您我们欺骗了您:ASP.NET MVC和ASP.NET Web窗体之间不共享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";
}
在HomeController.cs中,我已将Index方法更改为:
public ActionResult Index()
{
return RedirectToAction("About");
}
并将About方法更改为:
public ActionResult About()
{
Response.Write(Convert.ToString(HttpContext.Items["Test"]));
return View();
}
当我运行应用程序时,页面正确地重定向到/ Home / About和Response.Writes在global.asax.cs中设置正确的“Hello World”字符串。
所以,在我看来,好像我要么不明白这本书的含义 “像HttpContext.Items这样的东西不会被转移”或者它确实传输了这些东西,并且可以使用HttpContext.Items。
如果你们建议我避免使用HttpContext.Items,是否有另一种方法可以在每个请求的基础上在请求中存储对象?
答案 0 :(得分:38)
您的问题是提出一些问题,但我认为第1项是您正在寻找的答案。
在每个请求的基础上使用Context.Items
进行缓存是否可以?
是。如果正在处理中,每个请求,Web场中的每台计算机都是您的标准,那么Context.Items会为您提供该标准。
Context.Items
难以测试吗?
至于可测试性,我会将Context.Items
隐藏在某种界面后面。这样您就可以获得单元测试功能,而无需直接引用Context.Items
。否则,您需要测试Context.Items
的哪些内容?框架将存储和检索值?保持你的代码不知道System.Web
,你将成为一个快乐的露营者。
Context.Items
会RedirectToAction
生存吗?
不,您的测试无效。它在每个Web请求上设置“Hello,world”,并且您的测试跨越了两个Web请求。第一个是调用Index操作的时候。第二个是调用RedirectToAction
动作时(它是HTTP 302)。要使其失败,请在“索引”操作中设置一个新值,并查看它是否保留在“关于”操作中。
答案 1 :(得分:3)
使用TempData Dictionary,它主要用于在Actions重定向之间存储对象:
public ActionResult Index()
{
TempData.Add("Test", "Hello world");
return RedirectToAction("About");
}
public ActionResult About()
{
ViewData["Test"] = TempData["Test"];
return View();
}
然后检索视图中的值:
<%=ViewData["Test"] %>
答案 2 :(得分:1)
我做了一个测试,TempData确实在禁用会话状态时爆炸。我唯一的建议是不将对象本身存储在临时数据中,而是存储已建议的简单类型字段。由于您没有序列化对象树,因此不应该在运行过程中产生大的性能影响。