我使用的是Windows 7,IIS 7.5.7600.16385,目前安装了.NET 4.6.1,我们有一个MVC应用程序。
几天前,我们的应用程序出现了一些奇怪的行为。不幸的是,在Application_Start内部调用的服务不可用,并且在内部抛出了一个未处理的异常。我的预期行为是下一个请求再次调用 Application_Start(),或者下一个请求直接以 Application_BeginRequest() 开头,如如果在 Application_Start 中抛出未经处理的异常会发生什么?中所述。
不幸的是,我得到以下结果:
如果 Application_Start() 内部出现异常,我在第一个请求时收到错误 500。没关系。
在此之后,所有其他请求将返回在第一个请求时引发的异常。我通过在本地环境中抛出带有时间戳的异常来验证它。每个响应都包含带有第一个请求时间戳的异常,HTTP 答案仍为 500。它不依赖于调用哪个 url。在我们的代码中,没有命中断点,但 IIS 日志显示请求。答案似乎缓存在某个地方。
我个人喜欢这种行为,因为应用程序不会响应具有未定义初始化状态的请求。
是的,我知道在 Application_Start() 中调用其他服务资源不是最好的主意,下次我们可能会删除它:)
我的问题:
-
是否可以配置在 Application_Start() 引发异常时的行为?
-
也许有人知道这种行为何时被改变,或者它已经存在了很长时间?
好吧,我分析了这种情况并搜索了许多网站,但没有找到有关它的任何信息。但是,我设法观察到了这样的行为:
- 当未处理的错误抛入Application_Start时,IIS 返回错误页面,Web 应用开始关闭。
- 在关机期间(在我的例子中是 10 秒),任何新请求都由 IIS 处理,响应与第一个请求中的响应相同。如果您认为这是合乎逻辑的,因为IIS知道该网站正在关闭,因此很明显最后一个错误会导致它。
- 一段时间后,应用程序会引发Application_End事件,告知关闭已完成。在该事件之后,对网站的下一个请求将再次引发Application_Start,并将生成新的响应。
我认为您无法更改此行为,因为应用程序只需要一些时间来重新启动。
今天我有一些时间再次检查行为。我们在一些版本之前引入了Serilog,似乎配置对重新启动行为有影响。
protected void Application_Start()
{
SerilogManager.Configure(); //own class
using (LogContext.PushProperty(SerilogManager.PROPERTY_NAME_ComponentName, "xxx")){}
throw new Exception(DateTime.Now.ToString("hh:mm:ss"));
}
如果我从Application_Start中删除 PushProperty 行,那么重新启动将毫无问题地工作。使用此线路,不会调用Application_End。
现在我可以在私人和商业计算机上重现它。不知道为什么我的演示应用程序上次没有在我的商业机器上调用Application_end。