c# - 为什么HttpRequest结束后会第二次创建owin中间件

标签 c# asp.net-mvc-5 owin owin-middleware

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

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

经过大量研究后,我决定启动一个普通的 MVC 5 项目,而不使用任何身份验证。从 NuGet 添加 Owin 中间件后,我创建了以下 Owin Middleware 组件。它基本上检查 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));
            });
        }
    }
}

然后将其添加到 HomeControllerIndex ActionMethod 中,以检查创建的对象是否仍然存在。

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();
}

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

--- 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

那么为什么在注释end of 'normal' request之后,又创建并输入中间件呢?有人有任何想法或解释吗?

重现步骤:

  1. 在 VS 2013 中启动一个新的 MVC 5 项目,无需身份验证
  2. 使用包管理器中的 Install-Package Microsoft.Owin.Host.SystemWeb 从 NuGet 添加 Owin
  3. 将启动类添加到项目中,如上所示
  4. 将代码添加到HomeControllerIndex ActionMethod
  5. 在 Debug模式下按 F5
  6. 点击起始页上的“主页”链接
  7. 在输出(或立即取决于您的 VS 设置)窗口中观察输出

最佳答案

这里最有可能发生的情况是,实际上发生了两个单独的请求。第一个是您的主页/索引 View ,第二个可能是浏览器发出对 favicon.ico 之类的请求。 (浏览器往往会自动执行此操作。)

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

关于c# - 为什么HttpRequest结束后会第二次创建owin中间件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28820346/

相关文章:

c# - 在文本中查找查询匹配项

asp.net - 获取有关 URL 的路由信息

asp.net - 如何获取用户在 MVC 5 中注册的角色的 ID

c# - 你如何拒绝 Katana Bearer token 身份

c# - 请求/响应日志记录的响应正文

c# - 如果通过主机名访问 API,RestSharp 和 NTLM 身份验证不起作用

c# - 反序列化运行时创建的类

c# List<string> 赋值问题

c# - 从存储在数据库中的位置向 bing map 添加形状(bing map ajax 控件)

asp.net - 如何使用 MVC5 ASP.NET Identity Framework 对 SignalR .NET 客户端进行身份验证