C# 为什么在HttpRequest结束后第二次创建owin中间件

C# 为什么在HttpRequest结束后第二次创建owin中间件,c#,asp.net-mvc-5,owin,owin-middleware,C#,Asp.net Mvc 5,Owin,Owin Middleware,在一次关于Asp.Net中的ApplicationDbContext为什么会被创建并在每个请求中处理两次的讨论之后,我做了一些研究为什么会发生这种情况。我发现,ApplicationDbContext实际上是每个HttpRequest创建一次,但是当使用Owin管道时,Owin中间件将在HttpRequest结束后第二次创建 因此,当用户单击一个链接时,ApplicationDbContext确实是第二次创建的,给人的印象是每个WebRequest会创建两次对象 经过大量研究,我决定开始一个普通

在一次关于Asp.Net中的
ApplicationDbContext
为什么会被创建并在每个请求中处理两次的讨论之后,我做了一些研究为什么会发生这种情况。我发现,
ApplicationDbContext
实际上是每个
HttpRequest
创建一次,但是当使用Owin管道时,Owin中间件将在HttpRequest结束后第二次创建

因此,当用户单击一个链接时,
ApplicationDbContext
确实是第二次创建的,给人的印象是每个
WebRequest
会创建两次对象

经过大量研究,我决定开始一个普通的MVC5项目,而不使用任何身份验证。将我创建的NuGet中的Owin中间件添加到下面的
Owin中间件
组件之后。它基本上检查
HttpContext
字典中是否存在一些伪对象,并在不存在时创建一个伪对象。输出被写入调试窗口以保持简单

[assembly: OwinStartupAttribute(typeof(MvcPlain.Startup))]
namespace MvcPlain
{
    public class Startup {
        public static int Counter;
        public static string FakeKeyName;

        public void Configuration(IAppBuilder app) {
            app.Use(async (context, next) =>
            {
                Debug.WriteLine("Owin middleware entered => begin request");

                FakeKeyName = "owinKey" + Counter.ToString();
                var fakeKeyPresent = HttpContext.Current.Items.Contains(FakeKeyName);

                Debug.WriteLine(string.Format("{0} key present in HttpContext?: {1}", 
                                                        FakeKeyName, fakeKeyPresent));

                if (!HttpContext.Current.Items.Contains(FakeKeyName))
                {
                    Counter += 1;
                    HttpContext.Current.Items.Add(FakeKeyName, "someValue");
                }

                await next.Invoke();

                Debug.WriteLine("Owin middleware exited => end request");

                var keyStillPresent = HttpContext.Current.Items.Contains(FakeKeyName);
                Debug.WriteLine(string.Format("{0} still present in HttpContext?: {1}", 
                                                        FakeKeyName, keyStillPresent));
            });
        }
    }
}
然后将其添加到
HomeController
索引
操作方法中,以检查创建的对象是否仍然存在

public ActionResult Index()
{
    Debug.WriteLine("Index actionmethod called");
    var fakeKeyPresent = HttpContext.Items.Contains(Startup.FakeKeyName);

    Debug.WriteLine(string.Format("{0} key present in HttpContext?: {1}",
                                            Startup.FakeKeyName, fakeKeyPresent));

    return View();
}
运行时,输出窗口显示以下输出(为清晰起见添加了注释):

那么,为什么在“正常”请求的注释
结束后,会再次创建并输入中间件呢?有人有什么想法或解释吗

复制步骤:

  • 在VS 2013中启动新的MVC 5项目,无需验证
  • 使用包管理器中的安装包Microsoft.Owin.Host.SystemWeb从NuGet添加Owin
  • 向项目中添加一个启动类,如上所示
  • 将代码添加到
    家庭控制器的
    索引
    操作方法
  • 在调试模式下点击F5
  • 单击起始页上的“主页”链接
  • 在输出(或根据VS设置的即时)窗口中查看输出

  • 这里最有可能发生的是,实际上发生了两个独立的请求。第一个用于主页/索引视图,第二个可能是浏览器请求类似于
    favicon.ico
    的内容。(浏览器往往会自动执行此操作。)


    在中间件的开头,插入一个调试帮助程序,显示
    context.Request.Path
    的值,以查看每次请求的URL。

    您确定没有第二次请求fav图标、源地图、浏览器链接或类似的内容吗?你能打印HttpRequests的URL吗?看起来就是这样。但我很困惑。在上述测试项目中,情况确实如此。但是:昨天我使用了带有Asp.Net标识的模板,将其构建为发行版,并将其托管在“真实”的IIS环境中,并将上述信息记录到一个文本文件中。在这种情况下没有浏览器链接,而且还在发生。。。?有什么想法吗,favicon?很可能是favicon.ico的请求。这是大多数浏览器的一个相当全局的行为,不管浏览的是哪个网站。
    --- home link clicked ---
    Owin middleware entered => begin request
    owinKey2 key present in HttpContext?: False
    Index actionmethod called
    owinKey2 key present in HttpContext?: True
    Owin middleware exited => end request
    owinKey2 key still present in HttpContext?: True
    --- end of 'normal' request ---
    Owin middleware entered => begin request
    owinKey3 key present in HttpContext?: False
    Owin middleware exited => end request
    owinKey3 key still present in HttpContext?: True