2009-02-20 72 views
97

我目前在我的ASP.NET MVC应用程序中使用log4net来记录异常。我这样做的方式是让所有控制器都从BaseController类继承。在BaseController的OnActionExecuting事件,我登录可能发生的任何异常:记录ASP.NET MVC中的错误

protected override void OnActionExecuted(ActionExecutedContext filterContext) 
{ 
    // Log any exceptions 
    ILog log = LogManager.GetLogger(filterContext.Controller.GetType()); 

    if (filterContext.Exception != null) 
    { 
     log.Error("Unhandled exception: " + filterContext.Exception.Message + 
      ". Stack trace: " + filterContext.Exception.StackTrace, 
      filterContext.Exception); 
    } 
} 

如果控制器操作过程中发生未处理的异常,这个伟大的工程。

至于404错误,我有一个自定义的错误在我的web.config设置像这样:

<customErrors mode="On"> 
    <error statusCode="404" redirect="~/page-not-found"/> 
</customErrors> 

而且在处理了“页面未找到” URL控制器动作,我登录原始网址被要求:

[AcceptVerbs(HttpVerbs.Get)] 
public ActionResult PageNotFound() 
{ 
    log.Warn("404 page not found - " + Utils.SafeString(Request.QueryString["aspxerrorpath"])); 

    return View(); 
} 

而且这也行得通。

我遇到的问题是如何记录.aspx页面上的错误。比方说,我对网页或一些行内代码,将引发异常的一个编译错误:

<% ThisIsNotAValidFunction(); %> 
<% throw new Exception("help!"); %> 

看来,属性的HandleError正确地在共享文件夹重新路由这我Error.aspx页面,但绝对不会被我的BaseController的OnActionExecuted方法捕获。我想我可能会把日志代码放在Error.aspx页面上,但我不确定如何检索该级别的错误信息。

+0

ELMAH +1。这是我写的帮助你入门的[ELMAH教程](http://blog.elmah.io/elmah-tutorial/)。还要记住在使用ASP.NET MVC时使用[Elmah.MVC](https://www.nuget.org/packages/Elmah.MVC/)包,以避免定制错误页面等问题。 – ThomasArdal 2016-08-15 13:04:04

+0

Theres少数产品在那里会记录.NET应用程序中发生的所有错误。它们不像ELMAH或log4net那样低级,但如果您只是想监视和诊断错误,那么可以节省大量时间:[Bugsnag](https://docs.bugsnag.com/platforms/dotnet/) asp-net /)和[AirBrake](https://airbrake.io/languages/net_bug_tracker)是我所知道的两个.NET – 2017-09-12 01:05:42

回答

96

我会考虑通过插入Elmah来简化您的Web应用程序。

您将Elmah程序集添加到您的项目中,然后配置您的web.config。然后它将记录在控制器或页面级别创建的异常。它可以配置为登录到各种不同的地方(如SQL Server,电子邮件等)。它还提供一个Web前端,以便您浏览异常日志。

它是我添加到我创建的任何asp.net mvc应用程序的第一件事。

我仍然使用log4net,但我倾向于使用它来记录调试/信息,并将所有例外保留给Elmah。

您还可以在问题How do you log errors (Exceptions) in your ASP.NET apps?中找到更多信息。

+3

我最近开始使用Elmah,它是我最轻松和最简单的异常记录器之一曾用过。我读过一篇文章说MS应该将其包含在ASP.net中,我同意。 – dtc 2009-05-20 18:52:12

1

您可以尝试检查HttpContext.Error,但我不确定这一点。

2

您是否想过扩展HandleError属性?此外,斯科特在控制器/动作here上有一篇关于过滤拦截器的好博客文章。

1

的Error.aspx视图的定义是这样的:

namespace MvcApplication1.Views.Shared 
{ 
    public partial class Error : ViewPage<HandleErrorInfo> 
    { 
    } 
} 

的HandleErrorInfo有三个属性: 串ActionName 串ControllerName 异常异常

您应该能够访问HandleErrorInfo,因此,视图内的异常。

35

您可以挂钩Global.asax中的OnError事件。

事情是这样的:

/// <summary> 
/// Handles the Error event of the Application control. 
/// </summary> 
/// <param name="sender">The source of the event.</param> 
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> 
protected void Application_Error(object sender, EventArgs e) 
{ 
    if (Server != null) 
    { 
     Exception ex = Server.GetLastError(); 

     if (Response.StatusCode != 404) 
     { 
      Logging.Error("Caught in Global.asax", ex); 
     } 

    } 


} 
19

MVC3
创建属性,从HandleErrorInfoAttribute继承,包括您所选择的日志记录

public class ErrorLoggerAttribute : HandleErrorAttribute 
{ 
    public override void OnException(ExceptionContext filterContext) 
    { 
     LogError(filterContext); 
     base.OnException(filterContext); 
    } 

    public void LogError(ExceptionContext filterContext) 
    { 
     // You could use any logging approach here 

     StringBuilder builder = new StringBuilder(); 
     builder 
      .AppendLine("----------") 
      .AppendLine(DateTime.Now.ToString()) 
      .AppendFormat("Source:\t{0}", filterContext.Exception.Source) 
      .AppendLine() 
      .AppendFormat("Target:\t{0}", filterContext.Exception.TargetSite) 
      .AppendLine() 
      .AppendFormat("Type:\t{0}", filterContext.Exception.GetType().Name) 
      .AppendLine() 
      .AppendFormat("Message:\t{0}", filterContext.Exception.Message) 
      .AppendLine() 
      .AppendFormat("Stack:\t{0}", filterContext.Exception.StackTrace) 
      .AppendLine(); 

     string filePath = filterContext.HttpContext.Server.MapPath("~/App_Data/Error.log"); 

     using(StreamWriter writer = File.AppendText(filePath)) 
     { 
      writer.Write(builder.ToString()); 
      writer.Flush(); 
     } 
    } 

位置属性在Global.asax中RegisterGlobalFilters

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     // filters.Add(new HandleErrorAttribute()); 
     filters.Add(new ErrorLoggerAttribute()); 
    }