К основному контенту

Отображение сustomErrors страниц в случае ошибок 400, 404, 500 в MVC

В одном из предыдущих постов я писал о том, как фиксировать ошибки в MVC

Сегодня я расскажу как отображать user friendly страницы, если возникли ошибки 400, 404, 500 или любые другие страницы ошибок.

Предыстория вопроса. В asp.net данный вопрос решался просто. Достаточно было в файле web.config указать секцию:

<customErrors defaultRedirect="~/500.aspx" mode="RemoteOnly">
 <error redirect="404.aspx" statusСode="404"/>
 <error redirect="500.aspx" statusСode="500"/>
</customErrors >

Либо прописать страницы для отображения ошибок в IIS.

В случае с MVC дело обстоит иначе. Так как MVC использует свою схему для маршрутизации, то для подключения страниц отображения ошибок нужно сделать следующее.

Во-первых, создадим контроллер, который будет отвечать за отображение наших ошибок пользователю.

public class ErrorController : Controller
{
 //id - код ошибки
 public ActionResult StatusCode(int id)
 {
  //Игнорируем ошибки IIS
  Response.TrySkipIisCustomErrors = true;
  //Добавляем код ошибки в Response (важно для SEO)
  switch (id)
  {
   case 403:
    Response.StatusCode = (int)HttpStatusCode.Forbidden;
    break;
   case 404:
    Response.StatusCode = (int)HttpStatusCode.NotFound;
    break;
   case 500:
    Response.StatusCode = (int)HttpStatusCode.InternalServerError;
    break;
  }
  //Возвращаем представление пользователю
  return View(id);
 }
}

Для отображения ошибок в моем случае используется одно представление. Вы можете на каждый тип ошибки возвращать представление, которое захотите.

Что же нужно сделать, чтобы перехватывать ошибки и перенаправлять на наш контроллер?
Добавить маршрут в Global.asax!

protected void Application_Error(object sender, EventArgs e)
{//Когда произошла ошибка выполнить соответствующий метод
 if (Context.IsCustomErrorEnabled)
    ShowCustomErrorPage(Server.GetLastError());
}
//Метод, который возвращает код ошибки и перенаправляет на наш контроллер
private void ShowCustomErrorPage(Exception exception)
{
 HttpException httpException = exception as HttpException ?? new HttpException(500, "Internal Server Error", exception);
 Response.Clear();
 //Создаем новый маршрут
 RouteData routeData = new RouteData();
 routeData.Values.Add("controller", "Error");
 routeData.Values.Add("fromAppErrorEvent", true);
 switch (httpException.GetHttpCode())
 {
  case 403:
   routeData.Values.Add("action", "StatusCode");
   routeData.Values.Add("Id", "403");
   break;
  case 404:
   routeData.Values.Add("action", "StatusCode");
   routeData.Values.Add("Id", "404");
   break;
  case 500:
   routeData.Values.Add("action", "StatusCode");
   routeData.Values.Add("Id", "500");
   break;
  default:
   routeData.Values.Add("action", "StatusCode");
   routeData.Values.Add("Id", "500");
   routeData.Values.Add("httpStatusCode", httpException.GetHttpCode());
   break;
 }
 Server.ClearError();
 IController controller = new ErrorController();
 controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}

Последний штрих: написать в web.config     <customErrors mode="Off"/>

Комментарии

Отправить комментарий