asp.net-mvc ASP.Net MVC 异常记录结合错误处理
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1032373/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ASP.Net MVC Exception Logging combined with Error Handling
提问by Saajid Ismail
I am looking for a simple solution to do Exception Logging combined with Error Handling in my ASP.Net MVC 1.0 application.
我正在寻找一个简单的解决方案来在我的 ASP.Net MVC 1.0 应用程序中结合错误处理进行异常记录。
I've read lots of articles, including Questions posted here on StackOverflow, which all provide varying solutions for different situations. I am still unable to come up with a solution that suits my needs.
我已经阅读了很多文章,包括在 StackOverflow 上发布的问题,它们都为不同的情况提供了不同的解决方案。我仍然无法提出适合我需求的解决方案。
Here are my requirements:
以下是我的要求:
To be able to use the [HandleError] attribute (or something equivalent) on my Controller, to handle all exceptions that could be thrown from any of the Actions or Views. This should handle all exceptions that were not handled specifically on any of the Actions (as described in point 2). I would like to be able to specify which View a user must be redirected to in error cases, for all actions in the Controller.
I want to be able to specify the [HandleError] attribute (or something equivalent) at the top of specific Actions to catch specific exceptions and redirect users to a View appropriate to the exception. All other exceptions must still be handled by the [HandleError] attribute on the Controller.
In both cases above, I want the exceptions to be logged using log4net (or any other logging library).
为了能够在我的控制器上使用 [HandleError] 属性(或等效的东西),来处理可能从任何操作或视图抛出的所有异常。这应该处理所有未在任何操作上专门处理的异常(如第 2 点所述)。我希望能够为控制器中的所有操作指定在错误情况下必须将用户重定向到哪个视图。
我希望能够在特定操作的顶部指定 [HandleError] 属性(或等效的属性)以捕获特定异常并将用户重定向到适合该异常的视图。所有其他异常仍必须由控制器上的 [HandleError] 属性处理。
在上述两种情况下,我都希望使用 log4net(或任何其他日志记录库)记录异常。
How do I go about achieving the above? I've read about making all my Controllers inherit from a base controller which overrides the OnException method, and wherein I do my logging. However this will mess around with redirecting users to the appropriate Views, or make it messy.
我如何去实现上述目标?我已经阅读了关于让我的所有控制器从覆盖 OnException 方法的基本控制器继承的内容,并在其中进行日志记录。然而,这会导致将用户重定向到适当的视图,或者使它变得混乱。
I've read about writing my own Filter Action which implements IExceptionFilter to handle this, but this will conflict with the [HandleError] attribute.
我读过关于编写我自己的过滤器操作,它实现了 IExceptionFilter 来处理这个问题,但这会与 [HandleError] 属性冲突。
So far, my thoughts are that the best solution is to write my own attribute that inherits from HandleErrorAttribute. That way I get all the functionality of [HandleError], and can add my own log4net logging. The solution is as follows:
到目前为止,我的想法是最好的解决方案是编写我自己的继承自 HandleErrorAttribute 的属性。这样我就可以获得 [HandleError] 的所有功能,并且可以添加我自己的 log4net 日志记录。解决方法如下:
public class HandleErrorsAttribute: HandleErrorAttribute {
private log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public override void OnException(ExceptionContext filterContext)
{
if (filterContext.Exception != null)
{
log.Error("Error in Controller", filterContext.Exception);
}
base.OnException(filterContext);
}
}
Will the above code work for my requirements? If not, what solution does fulfill my requirements?
上面的代码能满足我的要求吗?如果没有,什么解决方案可以满足我的要求?
回答by Saajid Ismail
I'm still a bit confused with all the different solutions out there, and how attributes can interfere with each other, but I went with this solution:
我仍然对那里的所有不同解决方案以及属性如何相互干扰感到有些困惑,但我采用了这个解决方案:
public class LogErrorsAttribute: FilterAttribute, IExceptionFilter
{
#region IExceptionFilter Members
void IExceptionFilter.OnException(ExceptionContext filterContext)
{
if (filterContext != null && filterContext.Exception != null)
{
string controller = filterContext.RouteData.Values["controller"].ToString();
string action = filterContext.RouteData.Values["action"].ToString();
string loggerName = string.Format("{0}Controller.{1}", controller, action);
log4net.LogManager.GetLogger(loggerName).Error(string.Empty, filterContext.Exception);
}
}
#endregion
}
I still use the [HandleError] attribute as explained in the original question, and I just decorate each controller with a [LogErrors] attribute.
我仍然使用原始问题中解释的 [HandleError] 属性,我只是用 [LogErrors] 属性装饰每个控制器。
This works for me, as it keeps the error logging in one place and doesn't cause duplicate exceptions to be logged multiple times (which will happen if I extend [HandleError] and use the attribute in multiple places).
这对我有用,因为它将错误日志记录在一个地方,并且不会导致多次记录重复的异常(如果我扩展 [HandleError] 并在多个地方使用该属性,则会发生这种情况)。
I don't think it will be possible to combine both the Exception Logging and Error Handling into one atrribute or class, without it becoming very tedious and complex, or affecting the use of [HandleError]
我认为不可能将异常日志记录和错误处理合并到一个属性或类中,而不会变得非常繁琐和复杂,或者影响 [HandleError] 的使用
But this works for me since I decorate each controller only once, with the [LogErrors] attribute, and decorate Controllers and Actions with [HandleError] exactly how I want to, without them interfering with each other.
但这对我有用,因为我只用 [LogErrors] 属性装饰每个控制器一次,并完全按照我想要的方式用 [HandleError] 装饰控制器和操作,而它们不会相互干扰。
Update:
更新:
Here is an example of How I use it:
这是我如何使用它的示例:
[LogErrors(Order = 0)]
[HandleError(Order = 99)]
public class ContactController : Controller
{
public ActionResult Index()
{
return View(Views.Index);
}
public ActionResult Directions()
{
return View(Views.Directions);
}
public ActionResult ContactForm()
{
FormContactMessage formContactMessage = new FormContactMessage();
return View(Views.ContactForm,formContactMessage);
}
[HandleError(ExceptionType = typeof(SmtpException), View = "MessageFailed", Order = 1)]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ContactForm(FormContactMessage formContactMessage)
{
if (ModelState.IsValid)
{
if (formContactMessage.IsValid)
{
SmtpClient client = new SmtpClient();
MailAddress recipientAddress = new MailAddress(Properties.Settings.Default.ContactFormRecipientEmailAddress);
MailAddress senderAddress = new MailAddress(Properties.Settings.Default.ContactFormSenderEmailAddress);
MailMessage mailMessage = formContactMessage.ToMailMessage(recipientAddress, senderAddress);
client.Send(mailMessage);
return View("MessageSent");
}
else
{
ModelState.AddRuleViolations(formContactMessage.GetRuleViolations());
}
}
return View(Views.ContactForm, formContactMessage);
}
private static class Views
{
public static string Index { get { return "Index"; } }
public static string Directions { get { return "Directions"; } }
public static string ContactForm { get { return "ContactForm"; } }
}
}
In the above code, SmtpExceptions in the ContactFormaction overload are handled in a very specific way - the user is presented with a ViewPage specific to failed sent messages, in this case it is called "MessageFailed" . All other exceptions are handled by the default behaviour of [HandleError]. Also note that logging of errors occurs first, followed by handling of errors. This is indicated by the following:
在上面的代码中,ContactForm动作重载中的SmtpExceptions 以一种非常特殊的方式处理 - 用户会看到一个特定于失败发送消息的 ViewPage,在这种情况下,它被称为 "MessageFailed" 。所有其他异常都由 [HandleError] 的默认行为处理。另请注意,首先记录错误,然后处理错误。如下所示:
[LogErrors(Order = 0)]
[HandleError(Order = 99)]
Update:
更新:
There is an alternative solution to this, with a very good explanantion. I recommend reading through it to get a better understanding of the issues involved.
对此有一个替代解决方案,有一个很好的解释。我建议通读它以更好地了解所涉及的问题。
ASP.NET MVC HandleError Attribute, Custom Error Pages and Logging Exceptions(Thanks to Scott Shepherd below, who provided the link in an answer below).
ASP.NET MVC HandleError 属性、自定义错误页面和记录异常(感谢下面的 Scott Shepherd,他在下面的答案中提供了链接)。

