使用NLog处理错误并尝试捕获

时间:2015-12-05 04:32:13

标签: c# asp.net-mvc error-handling nlog elmah

我使用NLog在我的操作中记录错误,以使用其他信息存储错误,例如:

using NLog;

private static Logger _logger = LogManager.GetCurrentClassLogger();

public virtual ActionResult Edit(Client client)
{
  try
  {
        // FORCE ERROR
        var x = 0;

        x /= x;

        return RedirectToAction(MVC.Client.Index());
  }
  catch (Exception e)
  {
    _logger.Error("[Error in ClientController.Edit - id: " + client.Id + " - Error: " + e.Message + "]");
  }
}

我在Web.config中配置了错误处理:

<customErrors mode="On" />

但是当我执行Action(页面保留在同一个地方)时,我没有被重定向到Error.cshtml,为什么?

我可以用Elmah做同样的事情吗? (记录客户端ID等附加信息)

3 个答案:

答案 0 :(得分:3)

首先,大多数人通过而不是来捕获异常来解决此错误。这样,异常传播到ASP.NET,显示“500内部错误”网页,记录所有相关信息。

  • 如果您的服务器已配置为生产,则错误页面将只显示“发生错误,已记录详细信息。”

  • 如果服务器配置为开发,那么您将获得着名的黄页,其中包含异常类型,消息和堆栈跟踪。

吞下异常并手动重定向到错误页面是一种不好的做法,因为它会隐藏错误。有些工具可以检查您的日志并为您提供很好的统计信息,例如成功/失败请求的百分比,这些工具将不再有效。

所以,不要吞下这个例外是人们所做的事情,至少它会解决你的问题。

现在,我发现这非常笨重,因为我不喜欢手动查找黄页中提到的源文件并手动转到上面提到的行号。我几乎没有使用黄页,也可能只是说“发生了一个错误,给我一条河流哭,nah-nah-nah。”我不读黄页。

相反,我喜欢自己记录异常,我让记录器以full-path-to-source-filename(line):开始每一行,这样Visual Studio中调试日志的每一行都是可点击的,并自动点击一行打开正确的源文件,并滚动到发出日志消息的确切行。如果你想要这种奢侈品,那就继续捕捉异常,但是在记录异常之后你就必须重新抛出它,这样事情才能顺其自然。

<强> 修订

以下是评论中添加的一些信息:

因此,您可以执行以下操作:

try
{
   ...
}
catch (Exception e)
{
    log( "information" );
    throw; //special syntax which preserves original stack trace
}

或者

try
{
   ...
}
catch (Exception e)
{
    throw new Exception( "information", e ); //also preserves original stack trace
}

执行此操作:catch( Exception e ) { log( "information" ); throw e; }因为它丢失了e的原始堆栈跟踪信息。

答案 1 :(得分:1)

在您的代码中,错误发生在除法部分(x / = x),因此不执行重定向行(索引页)并跳转到捕获部分执行记录仪。您还必须在catch部分中定义重定向到Error.cshtml。

注意:当你使用try catch block时,在ASP.NET级别不会发生错误导致没有重定向到Error.cshtml页面

using NLog;

private static Logger _logger = LogManager.GetCurrentClassLogger();

public virtual ActionResult Edit(Client client)
{
  try
  {
        // FORCE ERROR
        var x = 0;

        x /= x; /// error occur here

        return RedirectToAction(MVC.Client.Index()); /// no execution of this line
  }
  catch (Exception e)
  {
    _logger.Error("[Error in ClientController.Edit - id: " + client.Id + " - Error: " + e.Message + "]");
    /// add redirect link here 
     return RedirectToAction(MVC.Client.Error()); /// this is needed since the catch block execute mean no error at ASP.net level resulting no redirect to default error page

  }
}

答案 2 :(得分:0)

这将简化您的异常处理,并允许您更简洁地管理流程。创建一个这样的属性:

 public class HandleExceptionAttribute : System.Web.Mvc.HandleErrorAttribute
    {
        // Pass in necessary data, etc
        private string _data;
        public string Data
        {
            get { return _data; }
            set { _data = value; }
        }

        public override void OnException(System.Web.Mvc.ExceptionContext filterContext)
        {            
            // Logging code here
            // Do something with the passed-in properties (Data in this code)
            // Use the filterContext to retrieve all sorts of info about the request
            // Direct the user

            base.OnException(filterContext);
        }
    }

现在,您可以在具有如下属性的控制器或方法级别上使用它:

[HandleException(Data="SomeValue", View="Error")]

或者,像这样全局注册(global.asax):

GlobalFilters.Filters.Add(new HandleExceptionAttribute());