使用 NLog 处理错误并尝试捕获
Handle Error with NLog and Try Catch
我使用 NLog 在我的 Actions 中记录错误,以存储带有附加信息的错误,例如:
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" />
但是当我执行操作时我没有被重定向到 Error.cshtml(页面保持在同一个地方),为什么?
我可以用 Elmah 做同样的事情吗? (记录客户端 ID 等附加信息)
这将简化您的异常处理并允许您更简洁地管理流程。像这样创建一个属性:
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());
在您的代码中,错误发生在 部分 (x/=x),因此没有执行 重定向行(索引页) 并跳转到执行记录器的 catch 部分。您还必须 在 catch 部分 中定义到 Error.cshtml 的重定向。
注意:当您使用 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
}
}
首先,大多数人通过不捕获异常来解决这个错误。这样,异常会传播到 ASP.NET,显示“500 内部错误”网页, 并且 所有相关信息都会被记录。
如果您的服务器配置为生产环境,错误页面只会显示 "an error occurred, details were logged."
如果服务器配置为开发,那么你会得到著名的黄页,其中包含异常类型、消息和堆栈跟踪。
吞下异常并手动重定向到错误页面是一种不好的做法,因为它隐藏了错误。有一些工具可以检查您的日志并为您提供很好的统计数据,例如 successful/failed 请求的百分比,这些将不再起作用。
所以,不吞下异常是人们所做的,至少,它解决了你的问题。
现在,我觉得这很笨拙,因为我不喜欢手动查找黄页中提到的源文件并手动转到提到的行号。黄页我基本没用,干脆说"an error occurred, cry me a river, 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
的原始堆栈跟踪信息。
我使用 NLog 在我的 Actions 中记录错误,以存储带有附加信息的错误,例如:
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" />
但是当我执行操作时我没有被重定向到 Error.cshtml(页面保持在同一个地方),为什么?
我可以用 Elmah 做同样的事情吗? (记录客户端 ID 等附加信息)
这将简化您的异常处理并允许您更简洁地管理流程。像这样创建一个属性:
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());
在您的代码中,错误发生在 部分 (x/=x),因此没有执行 重定向行(索引页) 并跳转到执行记录器的 catch 部分。您还必须 在 catch 部分 中定义到 Error.cshtml 的重定向。
注意:当您使用 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
}
}
首先,大多数人通过不捕获异常来解决这个错误。这样,异常会传播到 ASP.NET,显示“500 内部错误”网页, 并且 所有相关信息都会被记录。
如果您的服务器配置为生产环境,错误页面只会显示 "an error occurred, details were logged."
如果服务器配置为开发,那么你会得到著名的黄页,其中包含异常类型、消息和堆栈跟踪。
吞下异常并手动重定向到错误页面是一种不好的做法,因为它隐藏了错误。有一些工具可以检查您的日志并为您提供很好的统计数据,例如 successful/failed 请求的百分比,这些将不再起作用。
所以,不吞下异常是人们所做的,至少,它解决了你的问题。
现在,我觉得这很笨拙,因为我不喜欢手动查找黄页中提到的源文件并手动转到提到的行号。黄页我基本没用,干脆说"an error occurred, cry me a river, 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
的原始堆栈跟踪信息。