Подтвердить что ты не робот

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-бокса, хотя... не уверен, что это связано. У этого парня была та же проблема.

4b9b3361

Ответ 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-страница с головой и телом.