想实现:
404错误跳转到404.html没有小尾巴,500错误跳转到/View/Shared/Error,并且显示错误信息
现状:
使用httpErrors时,filterContext.HttpContext.IsCustomErrorEnabled为false,自带的HandleErrorAttribute将不满足条件不能执行。
自定义了一个ErrorExceptionAttribute,重写了OnException方法,ErrorExceptionAttribute将返回一次Result。
但是同时又会跳转到httpErrors里的500配置的路径,造成ErrorExceptionAttribute返回的Result被覆盖。
这样第一次Result里的错误信息就被第二次覆盖,而第二次没有错误信息
如果httpErrors和customErrors都配置,<customErrors mode="On"></customErrors>会造成filterContext.ExceptionHandled直接变成已处理
customErrors没有此问题,但是404错误会有小尾巴,状态码为200
问题:
1、为何HandleErrorAttribute只支持customErrors
2、如何在配置httpErrors时,只返回一次Result
愿景:
有没有办法不重写,直接使用HandleErrorAttribute
public override void OnException(ExceptionContext filterContext) { /* 自带异常处理只支持web.config中customErrors mode="On"的情况,不支持httpErrors, 所以下面重写,去掉了filterContext.HttpContext.IsCustomErrorEnabled检查 */ //base.OnException(filterContext); filterContext.CheckNull(nameof(filterContext)); if (!filterContext.IsChildAction && !filterContext.ExceptionHandled) { Exception innerException = filterContext.Exception; if ((new HttpException(null, innerException).GetHttpCode() == 500) && this.ExceptionType.IsInstanceOfType(innerException)) { string controllerName = (string)filterContext.RouteData.Values["controller"]; string actionName = (string)filterContext.RouteData.Values["action"]; HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName); ViewResult result = new ViewResult { ViewName = this.View, MasterName = this.Master, ViewData = new ViewDataDictionary<HandleErrorInfo>(model), TempData = filterContext.Controller.TempData }; filterContext.Result = result; filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.StatusCode = 500; filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; } } // ajax请求出现的异常返回json,否则上一步自带异常处理将跳转web.config指定的500错误页 if ((new HttpException(null, filterContext.Exception).GetHttpCode() == 500) && filterContext.HttpContext.Request.IsAjaxRequest()) { filterContext.Result = new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet, Data = new Result(StateCode.Fail, "Oops!服务器出现了内部错误。") }; } }
<httpErrors errorMode="Custom" existingResponse="Replace"> <clear /> <error statusCode="404" path="404.html" /> <error statusCode="500" responseMode="ExecuteURL" path="/Error" /> </httpErrors>
public class ErrorController : Controller { public ActionResult Index() { return View("Error"); } [ActionName("404")] public ActionResult NotFound() { return new HttpStatusCodeResult(HttpStatusCode.NotFound); } }
GlobalFilters.Filters.Add(new ErrorExceptionAttribute()); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
测试发现
filterContext.HttpContext.Response.StatusCode = 500;
这个会将页面转向配置文件里指定的500错误页,拿掉就不会,这样就可以显示错误信息
测试发现
这个会将页面转向配置文件里指定的500错误页,拿掉就不会,这样就可以显示错误信息
这里有几点需要配置:
1.服务器端是否将错误呈现给客户端
<customErrors mode="On"></customErrors>
On 指定启用自定义错误。如果未指定 defaultRedirect,用户将看到一般性错误。
Off 指定禁用自定义错误。这允许显示标准的详细错误。
RemoteOnly 指定仅向远程客户端显示自定义错误并且向本地主机显示 ASP.NET 错误。这是默认值。
默认值为 RemoteOnly。
2.iis是否显示 服务器端的错误信息
http://www.cnblogs.com/GISerYang/archive/2012/09/10/2679340.html
只有这2个都设置为可显示 那么浏览器才有可能显示错误信息
其次有关 StatusCode:
这个是http 返回码 自己可以在网上查找 200代表什么 300代表什么 400代表什么 500代表什么
改成200 可以完成功能 但是并不是一个良好的返回值 因为 这意味着 你将 一个本来错误的东西 以正确的输出进行返回了