2012-07-18 23 views
5

我有一個MVC 2的Web應用程序,即將發佈。到現在爲止,我已經關閉了自定義錯誤,但是我希望他們在生產準備就緒時能夠正常工作。使用MVC2的HandleErrorInfo - 模型爲null?

我已經建立了我的web.config有以下幾點:

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

404一個完美的作品,並NOTFOUND是直接映射到一個視圖,只是顯示一個非常標準的404頁,用我的行動自己的Site.Master文件。

對於404以外的任何內容,我希望用戶能夠查看異常詳細信息。 (這是一個內部應用程序,這樣做沒有安全風險)。

Error默認操作Index設置爲返回我已經定義的View()。我無法弄清楚的是如何將異常信息傳遞給View?

這看起來前途無量:

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

但是當我使用與查看:

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

錯誤頁面本身拋出一個錯誤,因爲HandleErrorInfo爲空。顯然,自定義錯誤中的一個錯誤會導致MVC2出現很多問題,其結果是黃色的死亡屏幕。

我猜想我錯過了博客中的某些關鍵字,或者它沒有解釋如何讓HandleErrorInfo成爲除null之外的任何內容,而無需爲每個控制器/操作設置Error屬性。

此外,我知道MVC3處理這個更好,我知道剃刀是非常好的。它沒有被用於這個項目,也不會改變這個項目來使用它。所以請不要使用「使用MVC3」的答案。

回答

12

HandleErrorInfo爲空,因爲您在customErrors中執行重定向。

這是我嘗試在我的最新項目中的想法,我更新了MVC 2.我沒有使用customErrors,因爲我不能在不執行重定向(我猜)的情況下調用控制器動作。

應用程序錯誤

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

全局錯誤處理程序

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

誤差控制器

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視圖

<%@ 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>