在ASP.NET MVC中logging错误

我目前在我的ASP.NET MVC应用程序中使用log4net来loggingexception。 我这样做的方式是让我所有的控制器都inheritance自一个BaseController类。 在BaseController的OnActionExecuting事件中,我logging了可能发生的任何exception:

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

如果在控制器操作期间发生未处理的exception,这非常有效。

至于404错误,我有我的web.config中设置自定义错误,如下所示:

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

而在处理“页面未find”url的控制器操作中,我logging了请求的原始URL:

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

这也是有效的。

我遇到的问题是如何logging.aspx页面上的错误。 假设我在其中一个页面上有一个编译错误,或者一些内联代码会抛出一个exception:

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

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

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

您将Elmah程序集添加到您的项目,然后configuration您的web.config。 然后它将logging在控制器或页面级创build的exception。 它可以configuration为login到各种不同的地方(如SQL Server,电子邮件等)。 它还提供了Web前端,以便您浏览exception日志。

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

我仍然使用log4net,但是我倾向于使用它来loggingdebugging/信息,并将所有exception保留给Elmah。

您也可以在问题中find更多信息如何在ASP.NET应用程序中logging错误(exception)? 。

您可以钩入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); } } } 

MVC3
创build从HandleErrorInfoAttributeinheritance的属性,并包括您select的日志logging

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

你有没有想过扩展HandleError属性? 此外,斯科特在这里有一个关于控制器/操作过滤拦截器的好博客文章。

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

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

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

HandleErrorInfo有三个属性:stringActionNamestringControllerNameexceptionexception

您应该能够访问HandleErrorInfo,并因此在视图中的exception。