ASP.NET MVC4 CustomErrors DefaultRedirect Игнорируется
У меня есть приложение MVC 4, используя специальный HandleErrorAttribute для обработки только пользовательских исключений. Я хотел бы перехватить страницы с ошибками по умолчанию 404 и другие не-500 и заменить их чем-то более привлекательным. С этой целью я добавил в свой Web.config следующее:
<system.web>
<customErrors mode="On" defaultRedirect="~/Error/Index" />
...
</ system.web>
У меня есть контроллер Error с методом Index и соответствующим представлением, но все же я получаю страницу ошибки 404 по умолчанию. Я также попытался установить мой defaultRedirect
в статический html файл безрезультатно. Я попытался добавить обработку ошибок, относящуюся к 404 внутри <customErrors>
, и я даже попытался модифицировать маршруты programattically, все без каких-либо результатов. Что мне не хватает? Почему ASP игнорирует мою обработку ошибок по умолчанию?
Примечание. Ранее я заметил, что локально не могу проверить свой атрибут CustomHandleErrorAttribute, даже с помощью <customErrors mode="On"
. Он работает, когда я ударил его на своем сервере из моего dev-бокса, хотя... не уверен, что это связано. У этого парня была та же проблема.
Ответы
Ответ 1
Это должно работать:
1. Web.Config
<customErrors mode="On"
defaultRedirect="~/Views/Shared/Error.cshtml">
<error statusCode="403"
redirect="~/Views/Shared/UnauthorizedAccess.cshtml" />
<error statusCode="404"
redirect="~/Views/Shared/FileNotFound.cshtml" />
</customErrors>
2. Зарегистрированный HandleErrorAttribute как глобальный фильтр действий в классе FilterConfig следующим образом
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CustomHandleErrorAttribute());
filters.Add(new AuthorizeAttribute());
}
Если это не работает, попытайтесь заставить себя передать ответ, проверив коды состояния, подобные приведенным в Global.asax: по крайней мере, он должен работать.
void Application_EndRequest(object sender, EventArgs e)
{
if (Response.StatusCode == 401)
{
Response.ClearContent();
Server.Transfer("~/Views/Shared/UnauthorizedAccess.cshtml");
}
}
Ответ 2
Я собираюсь немного не по теме. Я думал, что это немного важно объяснить.
![enter image description here]()
Если вы обратите внимание на выделенную выше часть. Я указал порядок действия фильтра действий. Это в основном описывает порядок выполнения Action Filter. Это ситуация, когда у вас есть несколько фильтров действий, реализованных по методу Controller/Action
![enter image description here]()
Эта фотография просто указывает, что пусть у вас есть два фильтра действий. OnActionExecution
начнет выполнение в приоритете, а OnActionExecuted
начнется снизу вверх. Это означает, что в случае OnActionExecuted
Action Filter, имеющий самый высокий порядок, будет выполняться первым, а в случае OnActionExecuting
Action Filter, имеющий самый низкий порядок, будет выполняться первым. Пример ниже.
public class Filter1 : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//Запуск начнется здесь - 1
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
//Выполнение будет двигаться здесь - 5
base.OnActionExecuted(filterContext);
}
}
public class Filter2 : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//Выполнение будет перемещено здесь - 2
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
//Выполнение будет двигаться здесь - 4
base.OnActionExecuted(filterContext);
}
}
[HandleError]
public class HomeController : Controller
{
[Filter1(Order = 1)]
[Filter2(Order = 2)]
public ActionResult Index()
{
//Выполнение будет двигаться здесь - 3
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
}
Возможно, вы уже знаете, что в рамках MVC существуют различные типы фильтров. Они перечислены ниже.
Внутри каждого фильтра вы можете указать свойство Order. Это в основном описывает порядок выполнения Action Filters.
Назад к исходному запросу
Это работает для меня. Это очень просто и не нужно рассматривать какие-либо изменения в Web.Config или зарегистрировать фильтр действий в файле Global.asax.
ок. Итак, сначала создаю простой фильтр действий. Это будет обрабатывать запросы Ajax и Non Ajax.
public class MyCustomErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
filterContext.ExceptionHandled = true;
var debugModeMsg = filterContext.HttpContext.IsDebuggingEnabled
? filterContext.Exception.Message +
"\n" +
filterContext.Exception.StackTrace
: "Your error message";
//Это тот случай, когда вам нужно обрабатывать запросы Ajax
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.Result = new JsonResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new
{
error = true,
message = debugModeMsg
}
};
}
//Это тот случай, когда вы обрабатываете запрос Non Ajax
else
{
var routeData = new RouteData();
routeData.Values["controller"] = "Error";
routeData.Values["action"] = "Error";
routeData.DataTokens["area"] = "app";
routeData.Values["exception"] = debugModeMsg;
IController errorsController = new ErrorController();
var exception = HttpContext.Current.Server.GetLastError();
var httpException = exception as HttpException;
if (httpException != null)
{
Response.StatusCode = httpException.GetHttpCode();
switch (System.Web.HttpContext.Current.Response.StatusCode)
{
case 404:
routeData.Values["action"] = "Http404";
break;
}
}
var rc = new RequestContext
(
new HttpContextWrapper(HttpContext.Current),
routeData
);
errorsController.Execute(rc);
}
base.OnException(filterContext);
}
}
Теперь вы можете реализовать этот фильтр действий на контроллере, а также только на Action. Пример:
![enter image description here]()
Надеюсь, это поможет вам.
Ответ 3
Создайте контрольный элемент ErrorController.
public class ErrorController : Controller
{
//
// GET: /Error/
public ActionResult Index()
{
return View();
}
}
Создайте представление индекса для действия.
в Web.config
<customErrors mode="On">
<error statusCode="404" redirect="Error/Index"/>
</customErrors>
Когда вы обрабатываете ошибки в коде/логике
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start application.";
return View("Index2");
}
}
[HandleError] - будет перенаправлен на страницу Error.cshtml внутри общей папки.
Ответ 4
Я не уверен, что этот ответ поможет вам, но это простой способ... Я поместил error.html в/и включил режим для пользовательских ошибок в веб-конфигурации, и это отлично работает...
<system.web>
<customErrors defaultRedirect="~/Error.html" mode="On" />
</system.web>
this error.html - это базовая html-страница с головой и телом.