我在自定义错误部分中结合使用 HandleErrorAttribute 和自定义错误控制器,以便在 MVC3 应用程序中处理错误。逻辑是通过 HandleErrorAttribute 中的 OnException 处理程序处理任何 Ajax 请求错误,并通过 ErrorController 处理其余错误。下面是代码 -
// Handle any ajax error via HandleErrorAttribute
public class HandleAjaxErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
public override void OnException(System.Web.Mvc.ExceptionContext filterContext)
{
filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
var exception = filterContext.Exception;
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
//some logic
filterContext.ExceptionHandled = true;
}
}
}
//Handle remaining errors in the Error Controller
public class ErrorController : Controller
{
protected override void HandleUnknownAction(string actionName)
{
var exception = Server.GetLastError(); //Can't get the exception object here.
//some logic
}
}
网络配置设置:
<customErrors mode="On" defaultRedirect="~/Error">
</customErrors>
当发生任何非 ajax 异常时,控制从 OnException 块流向错误控制器中的 HandleUnknownAction。但是我无法获取异常对象。如何在错误控制器中获取异常对象?
另外,您认为这种两步方法是处理 MVC3 中错误的正确方法吗?我想过使用 Application_Error 事件处理程序在集中位置处理错误,但根据我的研究,这不是 MVC 应用程序推荐的方法。
关于我上面的评论,我在这里粘贴我的代码是为了澄清我做了什么。
此代码位于 BaseController 中(强烈建议创建一个,请参阅本文:http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx)
我已经覆盖了 OnException 方法(我的主要目标是区分 Ajax 调用和常规调用):
protected override void OnException(ExceptionContext filterContext)
{
// Set to true or else it'll still propagate
filterContext.ExceptionHandled = true;
string message;
// Check if it's an Ajax request
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
// Here I check if the custom error is on, if it isn't I'll paste the
// stacktrace and the error
if (!filterContext.HttpContext.IsCustomErrorEnabled)
{
message = filterContext.Exception.Message + filterContext.Exception.StackTrace;
}
else
{
message = "Something went wrong";
}
// TODO: Decide what to do if ajax
filterContext.HttpContext.Response.StatusCode = 401;
var json = new JsonResult {Data = message};
json.ExecuteResult(this.ControllerContext);
}
else
{
// This is basically the same conditional, but instead of sending a JSON
// I'll redirect to a view and give it the exception
if (!filterContext.HttpContext.IsCustomErrorEnabled)
{
ViewData.Model = filterContext.Exception;
this.View("Error").ExecuteResult(this.ControllerContext);
}
else
{
this.View("../Error/ServerError").ExecuteResult(this.ControllerContext);
}
}
}
}
关于我上面的评论,重要的是要注意,我并不是说不使用 CustomError,而是只有在确实发生在管道之外的错误(例如 401)时才考虑它。
我可能是错的,但我相信您无需担心控制器中的错误信息,因为 MVC 会自动在视图中连接它。因此,如果您像这样制作(Razor)视图,它应该可以工作:
@model System.Web.Mvc.HandleErrorInfo
任何日志记录都可以在您的属性中完成,但如果您需要在错误控制器中执行此操作,请在错误控制器上创建一个 LogError 操作,该操作采用 HandleErrorInfo 参数并调用它,如下所示:
@Html.RenderAction("LogError", Model)
PS我还没有测试过这个,但它应该可以工作。
我的错误消息没有显示,错误控制器没有启动,直到我做了以下设置
<customErrors mode="On" defaultRedirect="~/Error">
</customErrors>