【发布时间】:2019-03-16 14:57:21
【问题描述】:
我有一个混合的 asp.net 网络表单/mvc 应用程序。当发生 500 错误时,我想执行以下操作:
- 如果错误发生在 Web 表单上,则显示自定义 *.aspx 页面。
- 如果错误发生在返回视图的控制器操作中,则显示自定义 mvc 视图。
- 如果错误发生在响应 $ajax 请求的控制器操作中,则显示用 javascript 构建的自定义消息。 这第三项是我遇到问题的地方。
在所有情况下,我都希望只记录一次错误。我在 global.asax Application_OnError 事件过程中记录 Web 表单错误。对于我的 mvc 控制器,我已将此调用添加到 Application_Start 事件过程:
GlobalFilters.Filters.Add(new HandleErrorAttribute());
然后创建了一个基类,应用程序中的所有控制器都从该基类派生。在这个基类中,我在 OnException 事件过程中记录错误。错误记录工作正常。
对于第 1 项,自定义 *.aspx 页面,我将其添加到我的 web.config 中,它成功地将所有 webforms 错误重定向到我的自定义错误页面:
<customErrors mode="On" defaultRedirect="MyFolder/MyDefaultErrorPage.aspx"
对于第 2 项,自定义 mvc 视图,我发现我需要在 web.config 的 httpErrors 元素中捕获 IIS 错误。这成功地将所有控制器错误重定向到我的自定义错误视图:
<httpErrors errorMode="Custom" existingResponse="Replace">
<clear />
<error statusCode="500" path="/MyFolder/MyErrorView" responseMode="Redirect"/>
</httpErrors>
上述所有方法都可以正常工作,但不幸的是,拦截 IIS 500 错误的第 2 项导致所有 $ajax 调用返回成功:事件处理程序而不是错误:事件处理程序,即使控制器操作抛出例外。例如,我从 javascript 调用控制器操作:
$.ajax({
type: "GET",
url: '/MyFolder/MyControllerAction',
success: function (data) {
do_something(data);
},
error: function (XMLHttpRequest, ajaxOptions, ex) {
show_error_message(XMLHttpRequest, ex);
}
问题在于,当 MyControllerAction 抛出异常时,调用的是“success:”事件处理程序,而不是“error:”事件处理程序。如果我从 web.config 中删除拦截 IIS 500 错误的节点,我会在 $ajax 调用中点击所需的“错误:”事件处理程序,但它显示默认的 IIS 500 错误页面,而不是我的自定义错误页面。
有没有什么方法可以为我的所有控制器错误显示自定义错误页面并且仍然有错误:当我从 javascript 执行 $ajax 调用时事件处理程序触发?
更新:如果我创建一个派生自 HandleErrorAttribute 的自定义类并在 GlobalFilters.Filters.Add() 中使用它,我就会成功。这会导致“错误:”事件在我的 javascript $ajax 调用中触发。问题是 XMLHttpRequest.responseText 不包含我的自定义消息(它只是说“页面无法显示,因为发生了内部服务器错误。”)。如果有任何方法可以将自定义消息传递给返回到 $.ajax 调用的 XMLHttpRequest.responseText?
public class MyCustomHandleErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
if(filterContext.HttpContext.Request.IsAjaxRequest()
&& filterContext.Exception != null)
{
//500 is needed so that $ajax "error:" event handler is hit, instead of "success:"
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
filterContext.Result = new JsonResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new
{
Message = "Custom message will go here"
}
};
//this stops Application_OnError from firing
filterContext.ExceptionHandled = true;
}
else
{
filterContext.Result = new ContentResult()
{
Content = "<html><body>Custom message will go here</body></html>",
ContentType = "text/html"
};
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
filterContext.ExceptionHandled = true;
}
}
【问题讨论】:
标签: javascript asp.net asp.net-mvc error-handling