Asp.Net Показать страницу ошибок по умолчанию, которая работает с $ ajax - PullRequest
0 голосов
/ 11 октября 2018

У меня есть гибридное приложение asp.net для веб-форм / mvc.Когда возникает ошибка 500, я хочу сделать следующее:

  1. показать пользовательскую страницу * .aspx, если ошибка произошла в веб-форме.
  2. показать пользовательское представление mvc, еслиПроизошла ошибка в действии контроллера, которое возвращает представление.
  3. показывает настраиваемое сообщение, созданное в javascript, если ошибка произошла в действии контроллера, которое отвечает на запрос $ ajax. В этом 3-м пункте у меня проблемы.

Во всех случаях я хочу зарегистрировать ошибку ровно один раз.Я регистрирую ошибки веб-форм в процедуре события global.asax Application_OnError.Для моих контроллеров mvc я добавил этот вызов в процедуру события Application_Start:

GlobalFilters.Filters.Add(new HandleErrorAttribute());

, а затем создал базовый класс, из которого происходят все контроллеры в приложении.В этом базовом классе я регистрирую ошибки в процедуре события OnException.Регистрация ошибок работает нормально.

Для элемента 1, пользовательской страницы * .aspx, я добавил ее в свой файл web.config, и он успешно перенаправляет все ошибки веб-форм на мою страницу пользовательских ошибок:

<customErrors mode="On" defaultRedirect="MyFolder/MyDefaultErrorPage.aspx" 

Для элемента2, пользовательское представление mvc, я обнаружил, что мне нужно перехватить ошибку IIS в элементе httpErrors в моем файле web.config.Это успешно перенаправляет все ошибки контроллера в мое пользовательское представление ошибок:

    <httpErrors errorMode="Custom" existingResponse="Replace">
  <clear />
  <error statusCode="500" path="/MyFolder/MyErrorView" responseMode="Redirect"/>
</httpErrors>

Все вышеперечисленное работает нормально, но, к сожалению, пункт 2, который перехватывает ошибку IIS 500, заставляет все вызовы $ 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, я получаю нужный обработчик события error: в моем вызове $ ajax, но он показывает страницу ошибки IIS 500 по умолчанию, а не мою пользовательскую страницу ошибки.

Есть ли способ показать пользовательскую страницу ошибок для всех моих ошибок контроллера и при этом все еще иметь ошибку: обработчик событий срабатывает при выполнении вызова $ ajax из javascript?

Обновление: если я создаюпользовательский класс, производный от HandleErrorAttribute и использующий его в GlobalFilters.Filters.Add ().Это вызывает событие «error:» в моем вызове javascript $ ajax.Проблема в том, что XMLHttpRequest.responseText не содержит моего настраиваемого сообщения (оно просто говорит: «Невозможно отобразить страницу, поскольку произошла внутренняя ошибка сервера».).Если есть какой-либо способ передать пользовательское сообщение в XMLHttpRequest.responseText, которое возвращается к вызову $ .ajax?

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;
        }
    }

1 Ответ

0 голосов
/ 11 октября 2018

Подводя итог: при возникновении ошибки во время выполнения на сервере я хочу иметь возможность передать пользовательское сообщение об ошибке в обработчик событий $ ajax (я не хочу сообщение об ошибке IIS по умолчанию), и я хочузапускаемая функция $ ajax «error:» (не функция «success:»).

Пользовательский атрибут HandleErrorAttribute, описанный в приведенном выше вопросе, работает, но для отмены сообщения об ошибке IIS по умолчанию требуется еще два изменения:

  1. Добавьте эту строку в первый блок if (блок if, обрабатывающий ошибку ajax) в процедуре OnException в пользовательском атрибуте:

    filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;

  2. Добавьте это к тегу httpErrors в web.config:

    errorMode = "Custom" существующийResponse = "PassThrough"

Значение для существующего ответа также может быть «Авто»

Мой последний настраиваемый атрибут выглядит следующим образом:

public class MyCustomHandleErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        //log the error
        if (filterContext.Exception != null)
        {
            //note that Application_Error makes the same call for errors it handles.
            //this method and Application_Error are the only two places in the application where errors are handled.
            MyErrorLogger(filterContext.Exception.GetBaseException());
        }

        if (filterContext.HttpContext.Request.IsAjaxRequest()
            && filterContext.Exception != null)
        {
            //this is an error from a $ajax call.
            //500 is needed so that $ajax "error:" function is hit, instead of "success:"
            filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

            filterContext.Result = new JsonResult()
            {
                Data = new 
                {
                    MyCustomMessage="A custom error message",
                    IsException = true
                }
            };

            //this stops Application_OnError from firing
            filterContext.ExceptionHandled = true;

            //this stops the web site from using the default IIS 500 error. 
            //in addition must set existingResponse="PassThrough" or "Auto" in web.config httpErrors element.
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
        }
        else
        {
            //this is an error in a controller method that returns a view
            filterContext.Result = new RedirectToRouteResult(
                new System.Web.Routing.RouteValueDictionary
                {
                    {"action", "Error500" },
                    {"controller", "Error" },
                    { "Message", "My custom message here."}
                });
            filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
            filterContext.ExceptionHandled = true;
        }
    }
}

Созданное выше сообщение об ошибке:проанализировал client-side как объект JSON в параметре «XMLHttpRequest.responseText» функции «error:»:

error: function (XMLHttpRequest, ajaxOptions, ex) {
    alert(jQuery.parseJSON(XMLHttpRequest.responseText).MyCustomMessage);
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...