为什么在HttpRequest结束后会第二次创建owin中间件
Why is owin middleware created a second time after the HttpRequest ended
在 question 之后,根据为什么 Asp.Net 中的 ApplicationDbContext
身份会根据请求创建和处理两次,我做了一些研究,为什么会发生这种情况。我发现 ApplicationDbContext
实际上是每个 HttpRequest
创建一次,但是当使用 Owin 管道时,Owin 中间件将在 HttpRequest 结束后第二次创建。
因此,当用户单击一个 link 时,ApplicationDbContext
确实是第二次创建,给人的印象是每个 WebRequest
.[=27 创建了两次对象=]
经过大量研究后,我决定在不使用任何身份验证的情况下启动一个普通的 MVC 5 项目。从我创建的 NuGet 添加 Owin 中间件到以下 Owin Middleware
组件后。它基本上检查 HttpContext
字典中是否存在某些假对象,并在不存在时创建一个。输出被写入调试 window 以保持简单。
[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
的 Index
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();
}
当 运行 输出 window 显示以下输出(为清楚起见添加注释):
--- 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
之后,中间件又被创建并进入了呢?有人有任何想法或解释吗?
重现步骤:
- 在没有身份验证的情况下在 VS 2013 中启动一个新的 MVC 5 项目
- 在包管理器中使用
Install-Package Microsoft.Owin.Host.SystemWeb
从 NuGet 添加 Owin
- 如上所示在项目中添加启动class
- 将代码添加到
HomeController
的 Index
ActionMethod
- 在调试模式下按 F5
- 点击起始页'Home' link
- 观察输出中的输出(或立即取决于您的 VS 设置)window
这里最有可能发生的是 实际上有两个 单独的请求正在发生。第一个是针对您的 Home/Index 视图,第二个可能是浏览器发出类似 favicon.ico
的请求。 (浏览器往往会自动执行此操作。)
在中间件的开头,插入一个显示 context.Request.Path
值的调试助手,以查看每次请求 URL 的内容。
在 question 之后,根据为什么 Asp.Net 中的 ApplicationDbContext
身份会根据请求创建和处理两次,我做了一些研究,为什么会发生这种情况。我发现 ApplicationDbContext
实际上是每个 HttpRequest
创建一次,但是当使用 Owin 管道时,Owin 中间件将在 HttpRequest 结束后第二次创建。
因此,当用户单击一个 link 时,ApplicationDbContext
确实是第二次创建,给人的印象是每个 WebRequest
.[=27 创建了两次对象=]
经过大量研究后,我决定在不使用任何身份验证的情况下启动一个普通的 MVC 5 项目。从我创建的 NuGet 添加 Owin 中间件到以下 Owin Middleware
组件后。它基本上检查 HttpContext
字典中是否存在某些假对象,并在不存在时创建一个。输出被写入调试 window 以保持简单。
[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
的 Index
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();
}
当 运行 输出 window 显示以下输出(为清楚起见添加注释):
--- 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
之后,中间件又被创建并进入了呢?有人有任何想法或解释吗?
重现步骤:
- 在没有身份验证的情况下在 VS 2013 中启动一个新的 MVC 5 项目
- 在包管理器中使用
Install-Package Microsoft.Owin.Host.SystemWeb
从 NuGet 添加 Owin - 如上所示在项目中添加启动class
- 将代码添加到
HomeController
的 - 在调试模式下按 F5
- 点击起始页'Home' link
- 观察输出中的输出(或立即取决于您的 VS 设置)window
Index
ActionMethod
这里最有可能发生的是 实际上有两个 单独的请求正在发生。第一个是针对您的 Home/Index 视图,第二个可能是浏览器发出类似 favicon.ico
的请求。 (浏览器往往会自动执行此操作。)
在中间件的开头,插入一个显示 context.Request.Path
值的调试助手,以查看每次请求 URL 的内容。