asp.net-mvc 使用 ASP.NET MVC 的 HttpContext.Items

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1134442/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-07 23:43:15  来源:igfitidea点击:

HttpContext.Items with ASP.NET MVC

asp.net-mvchttpcontext

提问by Ryan Hoffman

I'm implimenting my own ApplicationContext class that uses the singleton pattern. I want to store my instance of it in HttpContext.Items, since it is accessible in all parts of the request. I've been reading about using HttpContext with ASP.NET MVC and one of the major pains is that it introduces testing complexity. I've tried doing research on the testability of HttpContext.Items, but all I can find is stuff on Session. One of the only things I've found is out of a sample chapter in the Professional ASP.NET 3.5 MVC book on Wrox (pdf link here). On page 15 it says this:

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

Something You Can't Use: HttpContext.Items
Above in this section, we came clean and told you that we lied to you: HttpContext is not shared between ASP.NET MVC and ASP.NET Web Forms. As a result of this, you cannot use the HttpContext.Items collection to store and retrieve bits of data.

The reason for this is because once you redirect to a Controller, your HttpHandler becomes the System.Web.Mvc.MvcHandler, which is created using HttpContextWrapper, which will have its own definition of HttpContext.Current. Unfortunately, during this handshake, things like HttpContext.Items are not transferred.

What this boils down to is that the HttpContext types, despite looking and sounding very much the same, are not the same, and you cannot pass data in this way.

不能使用的东西:HttpContext.Items
在本节的上述内容中,我们坦白地告诉您,我们对您撒了谎:ASP.NET MVC 和 ASP.NET Web 窗体之间不共享 HttpContext。因此,您无法使用 HttpContext.Items 集合来存储和检索数据位。

这是因为一旦你重定向到一个控制器,你的 HttpHandler 就变成了 System.Web.Mvc.MvcHandler,它是使用 HttpContextWrapper 创建的,它有自己的 HttpContext.Current 定义。不幸的是,在这个握手过程中,诸如 HttpContext.Items 之类的东西没有被传输。

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

Now, I've tried testing this out, and as far as I can tell, if you redirect to another controller using RedirectToAction, HttpContext.Items does remain. I'm using the default ASP.NET MVC project to test this. What I've done is, add this method to Global.asax.cs:

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

protected void Application_BeginRequest()
{
    Context.Items["Test"] = "Hello World";
}

And in HomeController.cs, I've changed the Index method to:

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

public ActionResult Index()
{
    return RedirectToAction("About");
}

And changed the About method to:

并将 About 方法更改为:

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

When I run the application, the page properly redirects to /Home/About and Response.Writes the correct "Hello World" string set in the global.asax.cs.

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

So, it seems to me as if I'm either not understanding what the book is meaning when they say "things like HttpContext.Items are not transferred" OR it does transfer this stuff and it's okay to use HttpContext.Items.

所以,在我看来,当他们说“像 HttpContext.Items 之类的东西没有转移”时,我似乎不理解这本书的意思,或者它确实转移了这些东西,并且可以使用 HttpContext.Items。

If you guys recommend that I avoid HttpContext.Items, is there another alternative way to store an object across a request on a per-request basis?

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

回答by Nick Swarr

Your question is asking a few things but I think item #1 is the answer you're looking for.

您的问题是问一些问题,但我认为第 1 项是您正在寻找的答案。

  1. Is it fine to use Context.Itemsfor caching on a per request basis? Yes. If in process, per request, per machine in the web farm is your criteria then Context.Items gives you that.

  2. Is Context.Itemsdifficult to test with? As far as testability, I would hide Context.Itemsbehind an interface of some sort. This way you get unit testing capabilities without having to reference Context.Itemsdirectly. Otherwise, what do you need to test about Context.Items? That the framework will store and retrieve values? Keep your code ignorant of System.Weband you'll be a happy camper.

  3. Will Context.Itemssurvive RedirectToAction? No. Your test is invalid. It's setting "Hello, world" on every web request and your test spans two web requests. The first is when the Index action is called. The second is when RedirectToActionaction is called (it's an HTTP 302). To make it fail, set a new value in the Index action and see if it's retained in the About action.

  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 请求。第一个是调用索引操作的时间。第二个是RedirectToAction调用 action时(它是 HTTP 302)。要使其失败,请在 Index 操作中设置一个新值,然后查看它是否保留在 About 操作中。

回答by Ryan Hoffman

Use the TempData Dictionary, it is mainly for storing objects between Actions redirects:

使用 TempData Dictionary,它主要用于在 Actions 重定向之间存储对象:

public ActionResult Index()
{
    TempData.Add("Test", "Hello world");
    return RedirectToAction("About");
}

public ActionResult About()
{
    ViewData["Test"] = TempData["Test"];
    return View();
}

Then retrieve the value in your view:

然后在您的视图中检索值:

<%=ViewData["Test"] %>

回答by andymeadows

I did a test and TempData does, indeed, explode with session state disabled. My only advice would be to not store the object itself in temp data but store the simple typed fields as has been suggested. Since you're not serializing object trees it shouldn't be that big of a performance impact running out-of-process.

我做了一个测试,TempData 确实在禁用会话状态的情况下爆炸。我唯一的建议是不要将对象本身存储在临时数据中,而是按照建议存储简单类型的字段。由于您没有序列化对象树,因此在进程外运行时性能影响应该不会那么大。