2012-07-18 17 views
5

Tengo una aplicación web MVC 2, que está a punto de publicarse. Hasta ahora he desactivado los errores personalizados, pero me gustaría que funcionen cuando esté listo para la producción.HandleErrorInfo usando MVC2 - ¿El modelo es nulo?

he levantado mi web.config con lo siguiente:

<customErrors mode="On" defaultRedirect="/Error/"> 
    <error statusCode="404" redirect="/Error/NotFound "/> 
</customErrors> 

El 404 se trabaja perfectamente, y NotFound es una acción que corresponde directamente a una vista que solo muestra una página bastante estándar 404 usando mi propio archivo Site.Master.

Para cualquier cosa que no sea un 404, quiero que un usuario pueda ver los detalles de la excepción. (Esta es una aplicación interna, y no hay riesgo de seguridad al hacerlo).

La acción predeterminada ErrorIndex está configurada para devolver una Vista() que he definido. Lo que no puedo entender es cómo pasar la información de excepción a la Vista?

Esto parecía prometedor:

http://devstuffs.wordpress.com/2010/12/12/how-to-use-customerrors-in-asp-net-mvc-2/

Pero cuando se utiliza la vista con:

<%@ Page Title="" Language="C#" 
    MasterPageFile="~/Views/Shared/Bootstrap.Master" 
    Inherits="System.Web.Mvc.ViewPage<System.Web.Mvc.HandleErrorInfo>" %> 

La página de error en sí genera un error, como HandleErrorInfo es nulo. Obviamente, un error en el error personalizado causa MVC2 una gran cantidad de problemas, y el resultado es una pantalla amarilla de la muerte.

Supongo que olvidé algo clave en el blog, o no explica cómo hacer que HandleErrorInfo sea distinto de nulo sin establecer el atributo Error para cada uno de mis Controladores/Acciones.

Además, soy consciente de que MVC3 trata esto mejor, y soy consciente de que Razor es muy bueno. No se ha utilizado para este proyecto ni se cambiará este proyecto para usarlo. Entonces, por favor, no responda "Use MVC3".

Respuesta

12

HandleErrorInfo es nulo porque está realizando una redirección en customErrors.

Esta es la idea que estoy probando en mi último proyecto y actualicé para MVC 2. No usé customErrors porque no puedo invocar una acción del controlador sin realizar una redirección (supongo).

Error de aplicación

protected void Application_Error(Object sender, EventArgs e) 
{ 
    GlobalErrorHandler.HandleError(((HttpApplication)sender).Context, Server.GetLastError(), new ErrorController()); 
} 

error Global controlador de

public class GlobalErrorHandler 
{ 
    public static void HandleError(HttpContext context, Exception ex, Controller controller) 
    { 
     LogException(ex); 

     context.Response.StatusCode = GetStatusCode(ex); 
     context.ClearError(); 
     context.Response.Clear(); 
     context.Response.TrySkipIisCustomErrors = true; 

     if (IsAjaxRequest(context.Request)) 
     { 
      ReturnErrorJson(context, ex); 
      return; 
     } 

     ReturnErrorView(context, ex, controller); 
    } 

    public static void LogException(Exception ex) 
    { 
     // log the exception 
    } 

    private static void ReturnErrorView(HttpContext context, Exception ex, Controller controller) 
    { 
     var routeData = new RouteData(); 
     routeData.Values["controller"] = "Error"; 
     routeData.Values["action"] = GetActionName(GetStatusCode(ex)); 

     controller.ViewData.Model = new HandleErrorInfo(ex, " ", " "); 
     ((IController)controller).Execute(new RequestContext(new HttpContextWrapper(context), routeData)); 
    } 

    private static void ReturnErrorJson(HttpContext context, Exception ex) 
    { 
     var json = string.Format(@"success: false, error:""{0}""", ex.Message); 
     context.Response.ContentType = "application/json"; 
     context.Response.Write("{" + json + "}"); 
    } 

    private static int GetStatusCode(Exception ex) 
    { 
     return ex is HttpException ? ((HttpException)ex).GetHttpCode() : 500; 
    } 

    private static bool IsAjaxRequest(HttpRequest request) 
    { 
     return request.Headers["X-Requested-With"] != null && request.Headers["X-Requested-With"] == "XMLHttpRequest"; 
    } 

    private static string GetActionName(int statusCode) 
    { 
     string actionName; 

     switch (statusCode) 
     { 
      case 404: 
       actionName = "NotFound"; 
       break; 

      case 400: 
       actionName = "InvalidRequest"; 
       break; 

      case 401: 
       actionName = "AccessDenied"; 
       break; 

      default: 
       actionName = "ServerError"; 
       break; 
     } 

     return actionName; 
    } 

    public static bool IsDebug 
    { 
     get 
     { 
      bool debug = false; 

#if DEBUG 
      debug = true; 
#endif 
      return debug; 
     } 
    } 
} 

controlador Error

public class ErrorController : Controller 
{ 
    public ActionResult AccessDenied() 
    { 
     return View("AccessDenied"); 
    } 

    public ActionResult InvalidRequest() 
    { 
     return View("InvalidRequest"); 
    } 

    public ActionResult NotFound() 
    { 
     return View("NotFound"); 
    } 

    public ActionResult ServerError() 
    { 
     return View("ServerError"); 
    } 
} 

ServerError view

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<System.Web.Mvc.HandleErrorInfo>" %> 

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 
    ServerError 
</asp:Content> 

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 

    <h2>ServerError</h2> 

    <% if (Model.Exception != null) { %> 
     <p> 
      Controller: <%= Model.ControllerName %> 
     </p> 
     <p> 
      Action: <%= Model.ActionName %> 
     </p> 
     <p> 
      Message: <%= Model.Exception.Message%> 
     </p> 
     <p> 
      Stack Trace: <%= Model.Exception.StackTrace%> 
     </p> 
    <% } %> 

</asp:Content> 
Cuestiones relacionadas