2008-10-08 88 views
103

如何在asp.net MVC Preview 5中使用[HandleError]過濾器?
我設置在我的Web.config文件ASP.NET MVC HandleError

<customErrors mode="On" defaultRedirect="Error.aspx"> 
    <error statusCode="403" redirect="NoAccess.htm"/> 
    <error statusCode="404" redirect="FileNotFound.htm"/> 
</customErrors> 

的的customErrors抹的HandleError]我上面的控制器類是這樣的:

[HandleError] 
public class DSWebsiteController: Controller 
{ 
    [snip] 
    public ActionResult CrashTest() 
    { 
     throw new Exception("Oh Noes!"); 
    } 
} 

然後,我讓我的控制器繼承這個類,並呼籲撞擊測試() 在他們。 Visual Studio在錯誤時暫停,並在按f5繼續後,我重新路由到Error.aspx?aspxerrorpath =/sxi.mvc/CrashTest(其中sxi是所使用的控制器的名稱 )當然,無法找到路徑並且我得到「服務器錯誤‘/’應用。」 404

此網站從預覽3移植到5 一切運行(沒有那麼多的工作端口)以外的錯誤處理。 當我創建一個完整的新項目中的錯誤處理似乎工作。

想法?

--Note--
由於這個問題現在有超過3K的意見,我認爲這將是有益的,把我目前(ASP.NET MVC 1.0)使用。 在mvc contrib project有一個燦爛的屬性,叫做「RescueAttribute」 你或許應該看看太;)

+0

鏈接到`RescueAttribute`來源:http://mvccontrib.codeplex.com/SourceControl/changeset/view/4e8ad66c2a83#src%2fMVCContrib%2fFilters%2fRescueAttribute.cs – Peter 2012-01-13 12:24:11

回答

153
[HandleError] 

當你到你的類只提供的HandleError屬性(或爲此事你的操作方法),那麼當出現未處理的異常MVC將尋找在控制器的視圖命名爲「錯誤」第一對應的視圖夾。如果它不能找到它然後它會繼續在共享文件夾視圖看(這應該在默認情況下它的Error.aspx文件)

[HandleError(ExceptionType = typeof(SqlException), View = "DatabaseError")] 
[HandleError(ExceptionType = typeof(NullReferenceException), View = "LameErrorHandling")] 

您也可以疊起來用特定信息的附加屬性瞭解您正在尋找的異常類型。此時,您可以將錯誤指向除默認「錯誤」視圖以外的特定視圖。請致電Scott Guthrie's blog post

+1

感謝您的擴展信息。 我不知道我做錯了什麼,但我創建了一個新項目,移植了所有現有的視圖,控制器和模型,現在它可以工作。 雖然不知道選擇性的意見。 – 2008-10-10 19:27:25

+0

如果需要記錄這些異常,是否可以將視頻添加到代碼隱藏中? – 2009-04-01 15:09:43

+6

標誌性的,這裏是我的「比從未更好的遲到」回覆您的評論:您可以代替HandleErrorAttribute的子類並覆蓋它的「OnException」方法:然後插入任何需要的日誌記錄或自定義操作。然後,您可以完全處理該異常(將context.ExceptionHandled設置爲true),或者爲此延遲迴到基類自己的OnException方法。這裏有一篇很好的文章,可能有助於這個:http://blog.dantup.me.uk/2009/04/aspnet-mvc-handleerror-attribute-custom.html – Funka 2009-08-14 20:59:07

4

你缺少Error.aspx :)在預覽5,這是位於您的意見/共享文件夾。只需從新的預覽版5項目複製即可。

+0

感謝您的答覆,但我已經複製Error.aspx頁面。 確實可能是我通常會忘記的東西,但現在還沒有。 :P – 2008-10-09 06:41:09

23

還應當指出的是,其並不將HTTP錯誤代碼設定爲500

(例如UnauthorizedAccessException)

將不會被濾波器的HandleError處理的錯誤。

14

解HTTP錯誤代碼500 這是稱爲[ERROR]的屬性把它放在一個動作

public class Error: System.Web.Mvc.HandleErrorAttribute 
{ 
    public override void OnException(System.Web.Mvc.ExceptionContext filterContext) 
    { 

      if (filterContext.HttpContext.IsCustomErrorEnabled) 
      { 
       filterContext.ExceptionHandled = true; 

      } 
      base.OnException(filterContext); 
      //OVERRIDE THE 500 ERROR 
      filterContext.HttpContext.Response.StatusCode = 200; 
    } 

    private static void RaiseErrorSignal(Exception e) 
    { 
     var context = HttpContext.Current; 
     // using.Elmah.ErrorSignal.FromContext(context).Raise(e, context); 
    } 

} 

//例:

[Error] 
[HandleError] 
[PopulateSiteMap(SiteMapName="Mifel1", ViewDataKey="Mifel1")] 
public class ApplicationController : Controller 
{ 
} 
-1
[HandleError] 
    public class ErrorController : Controller 
    {   
     [AcceptVerbs(HttpVerbs.Get)] 
     public ViewResult NotAuthorized() 
     { 
      //401 
      Response.StatusCode = (int)HttpStatusCode.Unauthorized; 

     return View(); 
    } 

    [AcceptVerbs(HttpVerbs.Get)] 
    public ViewResult Forbidden() 
    { 
     //403 
     Response.StatusCode = (int)HttpStatusCode.Forbidden; 

     return View(); 
    } 

    [AcceptVerbs(HttpVerbs.Get)] 
    public ViewResult NotFound() 
    { 
     //404 
     Response.StatusCode = (int)HttpStatusCode.NotFound; 
     return View(); 
    } 

    public ViewResult ServerError() 
    { 
     //500 
     Response.StatusCode = (int)HttpStatusCode.NotFound; 
     return View(); 
    } 

}

14

MVC中的屬性在錯誤處理中非常有用get和post方法,它也跟蹤ajax調用

在您的應用程序中創建一個基礎控制器,並在您的主控制器(EmployeeController)中繼承它。

公共類EmployeeController:BaseController

添加以下代碼中基本控制器。

/// <summary> 
/// Base Controller 
/// </summary> 
public class BaseController : Controller 
{  
    protected override void OnException(ExceptionContext filterContext) 
    { 
     Exception ex = filterContext.Exception; 

     //Save error log in file 
     if (ConfigurationManager.AppSettings["SaveErrorLog"].ToString().Trim().ToUpper() == "TRUE") 
     { 
      SaveErrorLog(ex, filterContext); 
     } 

     // if the request is AJAX return JSON else view. 
     if (IsAjax(filterContext)) 
     { 
      //Because its a exception raised after ajax invocation 
      //Lets return Json 
      filterContext.Result = new JsonResult() 
      { 
       Data = Convert.ToString(filterContext.Exception), 
       JsonRequestBehavior = JsonRequestBehavior.AllowGet 
      }; 
     } 
     else 
     { 
      filterContext.ExceptionHandled = true; 
      filterContext.HttpContext.Response.Clear(); 

      filterContext.Result = new ViewResult() 
      { 
       //Error page to load 
       ViewName = "Error", 
       ViewData = new ViewDataDictionary() 
      }; 

      base.OnException(filterContext); 
     } 
    } 

    /// <summary> 
    /// Determines whether the specified filter context is ajax. 
    /// </summary> 
    /// <param name="filterContext">The filter context.</param> 
    private bool IsAjax(ExceptionContext filterContext) 
    { 
     return filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest"; 
    } 

    /// <summary> 
    /// Saves the error log. 
    /// </summary> 
    /// <param name="ex">The ex.</param> 
    /// <param name="filterContext">The filter context.</param> 
    void SaveErrorLog(Exception ex, ExceptionContext filterContext) 
    { 
     string logMessage = ex.ToString(); 

     string logDirectory = Server.MapPath(Url.Content("~/ErrorLog/")); 

     DateTime currentDateTime = DateTime.Now; 
     string currentDateTimeString = currentDateTime.ToString(); 
     CheckCreateLogDirectory(logDirectory); 
     string logLine = BuildLogLine(currentDateTime, logMessage, filterContext); 
     logDirectory = (logDirectory + "\\Log_" + LogFileName(DateTime.Now) + ".txt"); 

     StreamWriter streamWriter = null; 
     try 
     { 
      streamWriter = new StreamWriter(logDirectory, true); 
      streamWriter.WriteLine(logLine); 
     } 
     catch 
     { 
     } 
     finally 
     { 
      if (streamWriter != null) 
      { 
       streamWriter.Close(); 
      } 
     } 
    } 

    /// <summary> 
    /// Checks the create log directory. 
    /// </summary> 
    /// <param name="logPath">The log path.</param> 
    bool CheckCreateLogDirectory(string logPath) 
    { 
     bool loggingDirectoryExists = false; 
     DirectoryInfo directoryInfo = new DirectoryInfo(logPath); 
     if (directoryInfo.Exists) 
     { 
      loggingDirectoryExists = true; 
     } 
     else 
     { 
      try 
      { 
       Directory.CreateDirectory(logPath); 
       loggingDirectoryExists = true; 
      } 
      catch 
      { 
      } 
     } 

     return loggingDirectoryExists; 
    } 

    /// <summary> 
    /// Builds the log line. 
    /// </summary> 
    /// <param name="currentDateTime">The current date time.</param> 
    /// <param name="logMessage">The log message.</param> 
    /// <param name="filterContext">The filter context.</param>  
    string BuildLogLine(DateTime currentDateTime, string logMessage, ExceptionContext filterContext) 
    { 
     string controllerName = filterContext.RouteData.Values["Controller"].ToString(); 
     string actionName = filterContext.RouteData.Values["Action"].ToString(); 

     RouteValueDictionary paramList = ((System.Web.Routing.Route)(filterContext.RouteData.Route)).Defaults; 
     if (paramList != null) 
     { 
      paramList.Remove("Controller"); 
      paramList.Remove("Action"); 
     } 

     StringBuilder loglineStringBuilder = new StringBuilder(); 

     loglineStringBuilder.Append("Log Time : "); 
     loglineStringBuilder.Append(LogFileEntryDateTime(currentDateTime)); 
     loglineStringBuilder.Append(System.Environment.NewLine); 

     loglineStringBuilder.Append("Username : "); 
     loglineStringBuilder.Append(Session["LogedInUserName"]); 
     loglineStringBuilder.Append(System.Environment.NewLine); 

     loglineStringBuilder.Append("ControllerName : "); 
     loglineStringBuilder.Append(controllerName); 
     loglineStringBuilder.Append(System.Environment.NewLine); 

     loglineStringBuilder.Append("ActionName : "); 
     loglineStringBuilder.Append(actionName); 
     loglineStringBuilder.Append(System.Environment.NewLine); 

     loglineStringBuilder.Append("----------------------------------------------------------------------------------------------------------"); 
     loglineStringBuilder.Append(System.Environment.NewLine); 

     loglineStringBuilder.Append(logMessage); 
     loglineStringBuilder.Append(System.Environment.NewLine); 
     loglineStringBuilder.Append("=========================================================================================================="); 

     return loglineStringBuilder.ToString(); 
    } 

    /// <summary> 
    /// Logs the file entry date time. 
    /// </summary> 
    /// <param name="currentDateTime">The current date time.</param> 
    string LogFileEntryDateTime(DateTime currentDateTime) 
    { 
     return currentDateTime.ToString("dd-MMM-yyyy HH:mm:ss"); 
    } 

    /// <summary> 
    /// Logs the name of the file. 
    /// </summary> 
    /// <param name="currentDateTime">The current date time.</param> 
    string LogFileName(DateTime currentDateTime) 
    { 
     return currentDateTime.ToString("dd_MMM_yyyy"); 
    } 

} 

=========================================== =====

查找目錄:根/ App_Start/FilterConfig.cs

添加以下代碼:

/// <summary> 
/// Filter Config 
/// </summary> 
public class FilterConfig 
{ 
    /// <summary> 
    /// Registers the global filters. 
    /// </summary> 
    /// <param name="filters">The filters.</param> 
    public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new HandleErrorAttribute()); 
    } 
} 

跟蹤AJAX錯誤:

在佈局頁面加載中調用CheckAJAXError函數。

function CheckAJAXError() { 
    $(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) { 

     var ex; 
     if (String(thrownError).toUpperCase() == "LOGIN") { 
      var url = '@Url.Action("Login", "Login")'; 
      window.location = url; 
     } 
     else if (String(jqXHR.responseText).toUpperCase().indexOf("THE DELETE STATEMENT CONFLICTED WITH THE REFERENCE CONSTRAINT") >= 0) { 

      toastr.error('ReferanceExistMessage'); 
     } 
     else if (String(thrownError).toUpperCase() == "INTERNAL SERVER ERROR") { 
      ex = ajaxSettings.url; 
      //var url = '@Url.Action("ErrorLog", "Home")?exurl=' + ex; 
      var url = '@Url.Action("ErrorLog", "Home")'; 
      window.location = url; 
     } 
    }); 
}; 
相關問題