Asp.net mvc 3 当customerrors=”时,应用程序“错误未触发”;关于;
我在Asp.net mvc 3 当customerrors=”时,应用程序“错误未触发”;关于;,asp.net-mvc-3,application-error,Asp.net Mvc 3,Application Error,我在global.asax文件的Application\u Error事件中有代码,该事件在发生错误时执行,并通过电子邮件将错误的详细信息发送给我自己 void Application_Error(object sender, EventArgs e) { var error = Server.GetLastError(); if (error.Message != "Not Found") { // Send email here... }
global.asax
文件的Application\u Error
事件中有代码,该事件在发生错误时执行,并通过电子邮件将错误的详细信息发送给我自己
void Application_Error(object sender, EventArgs e)
{
var error = Server.GetLastError();
if (error.Message != "Not Found")
{
// Send email here...
}
}
当我在VisualStudio中运行它时,它工作得很好,但是当我发布到我们的实时服务器时,Application\u Error
事件不会触发
在一些测试之后,我可以在设置customErrors=“Off”
时触发应用程序错误,但是将其设置回customErrors=“On”
会阻止事件再次触发
有人能告诉我为什么在web.config
中启用customErrors
时Application\u Error
不会触发吗?据我所知,您正在将控制权传递给url参数中指定的页面,并且您的事件通知将位于此处,而不是Application\u Error
<customErrors defaultRedirect="myErrorPage.aspx"
mode="On">
</customErrors>
在这里可以找到很多信息:为了解决这个问题,我最终禁用了customerrors,并在global.asax中处理来自应用程序错误事件的所有错误。MVC有点棘手,因为我不想返回301重定向,我想返回合适的错误代码。更多细节可以在我的博客上查看,但最终代码如下所示
void Application_Error(object sender, EventArgs e)
{
var error = Server.GetLastError();
var code = (error is HttpException) ? (error as HttpException).GetHttpCode() : 500;
if (code != 404)
{
// Generate email with error details and send to administrator
}
Response.Clear();
Server.ClearError();
string path = Request.Path;
Context.RewritePath(string.Format("~/Errors/Http{0}", code), false);
IHttpHandler httpHandler = new MvcHttpHandler();
httpHandler.ProcessRequest(Context);
Context.RewritePath(path, false);
}
这是控制器
public class ErrorsController : Controller
{
[HttpGet]
public ActionResult Http404(string source)
{
Response.StatusCode = 404;
return View();
}
[HttpGet]
public ActionResult Http500(string source)
{
Response.StatusCode = 500;
return View();
}
}
更新
因为这个答案确实提供了一个解决方案,所以我不会对它进行编辑,但我找到了一个更干净的方法来解决这个问题。有关详细信息,请参阅
原始答案:
我弄明白了为什么没有调用Application\u Error()
方法
Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute()); // this line is the culprit
}
...
}
默认情况下(生成新项目时),MVC应用程序在Global.asax.cs
文件中有一些逻辑。此逻辑用于映射路由和注册筛选器。默认情况下,它只注册一个过滤器:一个HandleErrorAttribute
过滤器。当customErrors处于启用状态时(或通过远程请求,当它设置为RemoteOnly时),HandleErrorAttribute告诉MVC查找错误视图,并且它从不调用应用程序\u Error()
方法。我找不到这方面的文档,但在中进行了解释
要获取为每个未处理的异常调用的ApplicationError()方法,只需删除注册HandleErrorAttribute筛选器的行
现在的问题是:如何配置customErrors以获得您想要的
customErrors部分默认为redirectMode=“ResponseRedirect”
。您也可以将defaultRedirect属性指定为MVC路由。我创建了一个非常简单的ErrorController,并将我的web.config更改为如下所示
<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="~/Error.aspx">
<error statusCode="404" redirect="~/PageNotFound.aspx" />
</customErrors>
web.config
<customErrors mode="RemoteOnly" redirectMode="ResponseRedirect" defaultRedirect="~/Error">
<error statusCode="404" redirect="~/Error/PageNotFound" />
</customErrors>
此块告诉要使用正确的状态代码服务的页面。当然,在PageNotFound.aspx页面上,我使用了HttpStatusCode.NotFound
。我将我的web.config更改为如下所示
<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="~/Error.aspx">
<error statusCode="404" redirect="~/PageNotFound.aspx" />
</customErrors>
一切都很好
摘要:
- 删除以下行:
filters.Add(新HandleErrorAttribute())代码>
- 使用
Application\u Error()
方法记录异常
- 将customErrors与ResponseWrite一起使用,指向ASPX页面
- 让ASPX页面负责自己的响应状态代码
我注意到这个解决方案有几个缺点
- ASPX页面不能与Razor模板共享任何标记,我必须重写我们网站的标准页眉和页脚标记,以获得一致的外观和感觉
- *.aspx页面可以通过点击其URL直接访问
这些问题有解决的办法,但我对它们关注不够,没有做任何额外的工作
我希望这对每个人都有帮助 我通过创建一个ExceptionFilter并在那里记录错误而不是应用程序错误来解决这个问题。您只需在RegisterGlobalFilters中添加对in的调用
log4netExceptionFilter.cs
using System
using System.Web.Mvc;
public class log4netExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
Exception ex = context.Exception;
if (!(ex is HttpException)) //ignore "file not found"
{
//Log error here
}
}
}
Global.asax.cs
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new log4netExceptionFilter()); //must be before HandleErrorAttribute
filters.Add(new HandleErrorAttribute());
}
我喜欢Mark对ExceptionFilter的回答,但是如果您的所有控制器都派生自同一个基本控制器,那么另一个选择是简单地重写基本控制器中的一个异常。您可以在那里进行日志记录和发送电子邮件。这样做的好处是,可以使用IoC容器中已注入基本控制器的任何依赖项
您仍然可以将IoC与IEExceptionFilter一起使用,但配置绑定有点棘手。我发现了一种更简洁的方法,它描述了在MVC3 web应用中创建自定义错误页的方法,该方法不阻止记录异常
解决方案是使用
部分的元素
我像这样配置了我的Web.config
<httpErrors errorMode="DetailedLocalOnly" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL" />
<error statusCode="500" path="/Error" responseMode="ExecuteURL" />
</httpErrors>
视图非常简单,我只是使用标准的Razor语法来创建页面
仅此一点就足以让您在MVC中使用自定义错误页面
我还需要记录异常,所以我偷了使用自定义ExceptionFilter的机会
public class ExceptionPublisherExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext exceptionContext)
{
var exception = exceptionContext.Exception;
var request = exceptionContext.HttpContext.Request;
// log stuff
}
}
最后需要在Global.asax.cs文件中注册异常过滤器:
这感觉像是一个比我以前的答案更干净的解决方案,而且就我所知效果也一样好。我特别喜欢它,因为我不觉得我在与MVC框架抗争;这个解决方案实际上利用了它 这篇博客文章帮助了我:
如果您使用的是IIS 7.0或更高版本,则可以更改Web.config文件以处理过大的请求。有一些警告,但这里有一个例子:
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1048576" />
</requestFiltering>
</security>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="13" />
<error statusCode="404" subStatusCode="13" prefixLanguageFilePath="" path="/UploadTooLarge.htm" responseMode="Redirect" />
</httpErrors>
</system.webServer>
还请注意,当响应模式
为重定向
时,路径
属性必须是绝对路径,因此,如果相关,请在虚拟目录名称之前加上前缀。Jesse Webb的信息性回答展示了如何使用responseMode实现这一点
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new ExceptionPublisherExceptionFilter());
filters.Add(new HandleErrorAttribute());
}
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1048576" />
</requestFiltering>
</security>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="13" />
<error statusCode="404" subStatusCode="13" prefixLanguageFilePath="" path="/UploadTooLarge.htm" responseMode="Redirect" />
</httpErrors>
</system.webServer>
<system.web>
<httpRuntime maxRequestLength="10240" />
</system.web>
public class ExceptionPublisherExceptionFilter : IExceptionFilter
{
private static Logger _logger = LogManager.GetCurrentClassLogger();
public void OnException(ExceptionContext exceptionContext)
{
var exception = exceptionContext.Exception;
var request = exceptionContext.HttpContext.Request;
// HttpException httpException = exception as HttpException;
// Log this exception with your logger
_logger.Error(exception.Message);
}
}