У меня есть гибридное приложение asp.net для веб-форм / mvc.Когда возникает ошибка 500, я хочу сделать следующее:
- показать пользовательскую страницу * .aspx, если ошибка произошла в веб-форме.
- показать пользовательское представление mvc, еслиПроизошла ошибка в действии контроллера, которое возвращает представление.
- показывает настраиваемое сообщение, созданное в 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;
}
}