简体   繁体   English

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

[英]Handle Error with NLog and Try Catch

I log errors in my Actions using NLog to store errors with additional information, for example: 我使用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 + "]");
  }
}

And I have Error handling configured in Web.config: 而且我在Web.config中配置了错误处理:

<customErrors mode="On" />

But I don't get redirected to the Error.cshtml when I execute the Action (the page remains in the same place), why? 但是执行动作时,我没有重定向到Error.cshtml(页面保留在同一位置),为什么?

Can I use Elmah to do the same thing? 我可以用Elmah做同样的事情吗? (logging additional information like client Id) (记录其他信息,例如客户ID)

First of all, most people solve this error by not catching the exception. 首先,大多数人通过捕获异常来解决此错误。 This way, the exception propagates to ASP.NET, which displays a "500 Internal Error" webpage, and all the pertinent information is logged. 这样,异常会传播到ASP.NET,后者显示一个“ 500 Internal Error”网页, 记录所有相关信息。

  • If your server is configured for production, the error page will just say "an error occurred, details were logged." 如果您的服务器配置为生产环境,则错误页面将仅显示“发生错误,详细信息已记录”。

  • If the server is configured for development, then you will get the famous yellow page with the exception type, the message, and the stack trace. 如果将服务器配置为进行开发,则将获得著名的黄页,其中包含异常类型,消息和堆栈跟踪。

Swallowing the exception and manually redirecting to an error page is a bad practice because it hides errors. 吞下异常并手动重定向到错误页面是一种不好的做法,因为它会隐藏错误。 There are tools that examine your logs and give you nice statistics, for example about percentages of successful/failed requests, and these won't work any more. 有一些工具可以检查您的日志并为您提供良好的统计信息,例如有关成功/失败请求的百分比的信息,这些工具将不再起作用。

So, not swallowing the exception is what people do, and at the very least, it solves your problem. 因此,人们所做的就是不吞并例外,至少,它可以解决您的问题。


Now, I find this very clunky, because I do not like manually looking for the source files mentioned in the yellow page and manually going to the mentioned line numbers. 现在,我觉得这很笨拙,因为我不喜欢手动查找黄页中提到的源文件并手动转到所提到的行号。 I practically have no use for the yellow page, it might just as well just say "an error occurred, cry me a river, nah-nah-nah." 我实际上对黄页没有用,也可能只是说:“发生了一个错误,哭了我,一条河,不对不对。” I don't read the yellow page. 我没有看黄页。

Instead, I do like to log exceptions on my own, and I have my logger begin each line with full-path-to-source-filename(line): , so that every line on the debug log in visual studio is clickable, and clicking on a line automatically opens up the right source file, and scrolls to the exact line that issued the log message. 相反,我确实想自己记录异常,并且我的记录器使每行都以full-path-to-source-filename(line): ,这样Visual Studio中调试日志上的每一行都是可单击的,并且单击一行会自动打开正确的源文件,并滚动到发出该日志消息的确切行。 If you want this luxury, then go ahead and catch the exception, but right after logging the exception you have to rethrow it, so that things can follow their normal course. 如果您想要这种奢侈,请继续并捕获异常,但是在记录异常之后,您必须重新抛出异常,以使事情可以遵循正常的过程。

Amendment 修正案

Here is some information that was added in comments: 这是在注释中添加的一些信息:

So, you can do the following: 因此,您可以执行以下操作:

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

Or 要么

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

Do not do this: catch( Exception e ) { log( "information" ); throw e; } 要这样做: catch( Exception e ) { log( "information" ); throw e; } catch( Exception e ) { log( "information" ); throw e; } catch( Exception e ) { log( "information" ); throw e; } because it loses the original stack trace information of e . catch( Exception e ) { log( "information" ); throw e; }因为它会丢失e的原始堆栈跟踪信息。

In your code, error occur at the division portion(x/=x) so no execution of redirect line(index page) and jump to catch portion executing the logger. 在您的代码中, 除法部分(x / = x)发生错误,因此没有执行重定向行(索引页) ,而是跳转到捕获执行记录器的部分。 You have to define the redirect to Error.cshtml in catch portion also. 您还必须在catch部分中定义对Error.cshtml的重定向

Note: when you use try catch block error will not occur at ASP.NET level resulting no redirect to Error.cshtml page 注意:使用try catch块时,在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

  }
}

This will streamline your exception handling and allow you to manage the process more succinctly. 这将简化您的异常处理,并使您可以更简洁地管理流程。 Create an attribute like this: 创建一个这样的属性:

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

Now you can use it on a controller or method level with an attribute like this: 现在,您可以在具有此类属性的控制器或方法级别上使用它:

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

Or, register it globally (global.asax) like this: 或者,像这样在全局(global.asax)中注册它:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM