我仍然对所有不同的解决方案以及属性如何相互干扰感到有些困惑,但我选择了这个解决方案:
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
}
我仍然使用原始问题中解释的 [HandleError] 属性,我只是用 [LogErrors] 属性装饰每个控制器。
这对我有用,因为它将错误日志记录在一个地方,并且不会导致多次记录重复的异常(如果我扩展 [HandleError] 并在多个地方使用该属性就会发生这种情况)。
我认为不可能将异常记录和错误处理合并到一个属性或类中,否则会变得非常繁琐和复杂,或者不影响 [HandleError] 的使用
但这对我有用,因为我只使用 [LogErrors] 属性装饰每个控制器一次,并使用 [HandleError] 完全按照我想要的方式装饰控制器和操作,而不会相互干扰。
更新:
这是我如何使用它的示例:
[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"; } }
}
}
在上面的代码中,ContactForm 动作重载中的 SmtpExceptions 以一种非常具体的方式处理 - 向用户呈现一个特定于发送失败消息的 ViewPage,在本例中称为“MessageFailed”。所有其他异常都由 [HandleError] 的默认行为处理。另请注意,首先记录错误,然后处理错误。如下所示:
[LogErrors(Order = 0)]
[HandleError(Order = 99)]
更新:
有一个替代解决方案,有一个很好的解释。我建议通读一遍以更好地理解所涉及的问题。
ASP.NET MVC HandleError Attribute, Custom Error Pages and Logging Exceptions
(感谢下面的 Scott Shepherd,他在下面的答案中提供了链接)。