我正在尝试处理global.asax中MVC 3项目的所有应用程序异常,虽然一切都在Cassini中正常工作,但一旦我部署到IIS 7.5,IIS就开始从我的应用程序中控制并处理许多例外本身。这会导致绕过我的自定义日志记录并返回丑陋的视图。
我对Darin的answer到this question采用了类似的方法。这就是我现在正在使用的内容。
protected void Application_Error(object sender, EventArgs e)
{
var app = (MvcApplication)sender;
var context = app.Context;
var exception = app.Server.GetLastError();
LogExceptionDetails(exception, Request.Url.PathAndQuery);
context.Response.Clear();
context.ClearError();
string redirectTo = "/error";
HttpException httpException = exception as HttpException;
if (httpException != null)
{
switch (httpException.GetHttpCode())
{
case 403:
redirectTo += "/forbidden";
break;
case 404:
redirectTo += "/notfound";
break;
}
}
Response.TrySkipIisCustomErrors = true;
// I should really change this so I can return a proper statusCode
Response.Redirect(redirectTo);
}
例如,导航到localhost/app_code
将返回一个丑陋的视图,不会被记录。我设法通过使用:
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="403" />
<error statusCode="403" path="/error/forbidden" responseMode="ExecuteURL" />
<remove statusCode="404" />
<error statusCode="404" path="/error/notfound" responseMode="ExecuteURL" />
</httpErrors>
但这并不能解决日志问题。
我尝试过的其他事情包括:
existingResponse="PassThrough"
。<clear />
。httpErrors
有和没有customErrors
的各种组合。<modules runAllManagedModulesForAllRequests="true" />
。Response.TrySkipIisCustomErrors = true;
有没有办法以编程方式处理这个问题,同时保持集中在global.asax中,而不是搞乱web.config?
答案 0 :(得分:0)
是。这就是我正在做的事情,但不幸的是它并不完美。
首先,关闭自定义错误。
<customErrors mode="Off" />
接下来,将HttpErrors更改为Detailed。请注意,这是我不太喜欢的部分,主要是因为如果你这样做,似乎你可能会使你的堆栈跟踪可访问。我想只要你在错误处理中处理所有状态代码,通过使用catch all,你应该没问题。如果我错了,请纠正我。
<httpErrors errorMode="Detailed" />
您还需要在global.asax中使用catch all route
来捕获与您定义的路线不匹配的所有MVC路线,并将它们发送到您的404.这可能会有问题,具体取决于您的路线设置,主要是,如果您依靠捕获所有路线来处理您当前的非404路线。我使用反射来根据我的控制器中的Action方法定义所有路由,因此我不依赖于应用程序路径的catch all模式。
最后,处理global.asax中的错误。使用catch all(例如500)并针对您想要的任何内容执行特殊路由,例如404错误。
protected void Application_Error(object sender, EventArgs e)
{
var ex = Server.GetLastError().GetBaseException();
Server.ClearError();
var routeData = new RouteData();
routeData.Values.Add("controller", "Error");
routeData.Values.Add("action", "500");
if (ex.GetType() == typeof (HttpException))
{
var httpException = (HttpException) ex;
var code = httpException.GetHttpCode();
// Is it a 4xx Error
if (code % 400 < 100)
{
routeData.Values["action"] = "404";
}
}
IController errorController = new ErrorController();
errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}
请注意,在我的示例中,我将除4xx错误之外的所有错误视为500.此外,在此示例中,我使用名为“ErrorController”的控制器和两个名为“500”和“404”的操作。
我希望这会有所帮助,如果您找到需要设置为“详细”的HttpErrors的解决方法,请分享!