2009-06-23 4 views
22

내 ASP.Net MVC 1.0 응용 프로그램에서 오류 처리와 결합 된 예외 로깅을 수행하는 간단한 솔루션을 찾고 있습니다.오류 처리와 함께 ASP.Net MVC 예외 로깅

여기에는 StackOverflow에 게시 된 질문을 비롯하여 다양한 상황에 대한 다양한 솔루션을 제공하는 기사가 많이 있습니다. 나는 아직도 나의 필요에 맞는 해결책을 찾을 수 없다. 여기

내 요구 사항 :

  1. 액션 또는 뷰의에서 발생 될 수있는 모든 예외를 처리하기 위해, 내 컨트롤러에 [는 handleError] 속성 (또는 이에 해당하는)를 사용 할 수 있으려면 . 이것은 모든 Action에서 특별히 처리되지 않은 모든 예외를 처리해야합니다 (2 번에서 설명). 컨트롤러의 모든 작업에 대해 오류가 발생한 경우 사용자가 어떤보기로 리디렉션되어야하는지 지정할 수 있습니다.

  2. 특정 조치의 맨 위에 [HandleError] 특성 (또는 이와 동등한 것)을 지정하여 예외에 적합한 예외로 사용자를 리디렉션 할 수 있기를 원합니다. 다른 모든 예외는 여전히 컨트롤러의 [HandleError] 속성에 의해 처리되어야합니다.

  3. 위의 두 가지 경우 모두 log4net (또는 다른 로깅 라이브러리)을 사용하여 예외가 기록되도록하고 싶습니다.

위의 목표를 달성하려면 어떻게해야합니까? 모든 Controllers를 OnException 메서드를 재정의하는 기본 컨트롤러에서 상속받으며 내 로깅을 수행하는 방법에 대해 읽었습니다. 그러나 이것은 사용자를 적절한 뷰로 리다이렉트 시키거나 지저분 해 지도록 만들 것이다.

이 문제를 처리하기 위해 IExceptionFilter를 구현하는 자체 Filter Action을 작성했지만이 문제는 [HandleError] 속성과 충돌합니다.

지금까지 내 생각에 가장 좋은 해결책은 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); 
     } 
    } 

위 코드가 내 요구 사항에 부합합니까? 그렇지 않은 경우 어떤 솔루션이 내 요구 사항을 충족합니까?

답변

24

나는 거기에 여전히 다른 솔루션을 조금 혼란 스러워요, 어떻게 속성은 서로 간섭 할 수 있지만, 나는이 솔루션을했다 :

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]

의 사용에 영향을주지 않고, 예외 로깅 및 하나 atrribute 또는 클래스에 오류 처리를 모두 결합 할 수있을 것입니다 생각하지 않습니다

그러나이 [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)] 

업데이트 : 아주 좋은 explanantion이 대안 솔루션,있다

. 나는 그 문제를 더 잘 이해하기 위해 그것을 읽는 것이 좋습니다.

ASP.NET MVC HandleError Attribute, Custom Error Pages and Logging Exceptions (아래 Scott Shepherd에게 감사의 말을 전하는 응답)

+0

니스, 대단히 감사합니다. 저는 이것을 사용할 것입니다. – Kezzer

+3

이 코드에는 RouteData.Values ​​[ "action"]에 대해 null이 반환되지 않는다고 가정하는 버그가있는 것으로 의심됩니다. --ToString()을 호출하면 오류 처리기가 NullReferenceException을 throw 할 수 있습니다. 오류 처리기가 오류를 발생시키는 것보다 더 실망스러운 것은 없습니다. –