2013-11-29 4 views
0

Я работаю над созданием пользовательских страниц ошибок в моем веб-приложении ASP.NET MVC 4. Я уже реализовал обработку ошибок OnException и декорирование контроллеров с помощью атрибутов, но мне захотелось создать собственные страницы ошибок для URL-адресов, которые не попадали под какие-либо маршруты контроллера, поэтому я прибегал к Application_Error от Global.asax.ASP.NET MVC 4 Custom Error Views issue

После ответа @ Darin's (спасибо btw!) В этом вопросе here, у меня есть все, что нужно настроить, но я получаю проблему, когда контроллер отображает представление на стороне клиента. Когда он возвращает представление, он возвращает весь HTML-код, отображаемый внутри тега <pre>. Я использую инструменты разработчика Chrome, когда вижу это. Это происходит в Chrome, Safari и Mozilla (возможно, больше, я не потрудился проверить после них). Как это ни странно, представления выглядят отлично в IE. Я googled вокруг и посмотрел вокруг другие вопросы и не нашел много на этом. Кто-нибудь случайно узнает, как/почему это происходит, и обходное решение для этого? Как последнее усилие, я подумал о том, чтобы получить представление как строку и вместо этого использовать return Content(...), но, похоже, немного для того, что стоит.

tl; dr - Если бы я мог внести свой вклад в то, почему мой взгляд HTML визуализируется внутри тега <pre>, это было бы замечательно! Я уверен, что это специфичный для браузера рендеринг, но я не собираюсь останавливаться на этом только в IE.

Контроллер:

public class ErrorsController : Controller 
{  

    public ActionResult PageNotFound() 
    { 
     Response.StatusCode = 404; 

     var vm = new ErrorViewModel() 
     { 
      ErrorMessage = "The page you requested could not be found.", 
      StatusCode = Response.StatusCode 
     }; 

     Response.TrySkipIisCustomErrors = true;    
     return View("PageNotFound", vm); 
    } 

Вид:

@{ 
Layout = "~/Views/Shared/_GenericLayout.cshtml"; 
} 

<h1 class="error">Oh No!</h1> 

@if(Model.ErrorMessage != null && Model.StatusCode != null) 
{ 
    <h2><em>@Model.StatusCode</em> - @Model.ErrorMessage</h2> 
} 
else 
{ 
    <h2>The page you requested could not be found.</h2>  
} 

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; 

     Response.Clear(); 

     RouteData routeData = new RouteData(); 
     routeData.Values.Add("controller", "Errors"); 
     routeData.Values.Add("fromAppErrorEvent", true); 

     if (httpException != null) 
     { 
      Response.StatusCode = httpException.GetHttpCode(); 
      switch(Response.StatusCode) 
      { 
       case 404: 
        routeData.Values.Add("action", "PageNotFound"); 
        break; 
       case 403: 
        routeData.Values.Add("action", "PageForbidden"); 
        break; 
      } 
     } 

     Server.ClearError(); 

     IController controller = new ErrorsController(); 
     RequestContext rc = new RequestContext(new HttpContextWrapper(Context), routeData); 
     controller.Execute(rc); 
    } 

ответ

3

Простое исправление. Chrome не узнал, что он получает, поэтому явно указывая тип контента ответа на «text/html», прежде чем возвращать представление, исправлена ​​проблема.

public ActionResult PageNotFound() 
{ 
    Response.StatusCode = 404; 

    var vm = new ErrorViewModel() 
    { 
     ErrorMessage = "The page you requested could not be found.", 
     StatusCode = Response.StatusCode 
    }; 

    Response.ContentType = "text/html"; 
    Response.TrySkipIisCustomErrors = true;    
    return View("PageNotFound", vm); 
}