2008-10-08 49 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; 
     } 
    }); 
}; 
相关问题