2012-07-12 9 views
10

का उपयोग कर एक MVC3 वेब अनुप्रयोग में मैंMVC [HandleError] जब वैश्विक लॉगिंग

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 
    filters.Add(new HandleErrorAttribute()); 
} 

उपयोग कर रहा था वैश्विक त्रुटि हैंडलिंग जहां उपयोगकर्ता 'त्रुटि' दृश्य दिखाया गया था, तो एक बिना क्रिया का अपवाद हुई लागू करने के लिए दो बार बुलाया HandleErrorAttribute।

एक विशेष दृश्य के लिए, यदि [HandleError(View = "SpecialError")] के साथ विधि को सजाने के द्वारा एक अनचाहे अपवाद हुआ तो भी मैं एक अलग त्रुटि दृश्य प्रदर्शित करना चाहता था। यह ठीक काम किया।

मैं फिर वैश्विक लॉग इन अनचाहे अपवादों को जोड़ना चाहता था। बजाय इस विशेषता नाम का उपयोग करने के

public class MyHandleErrorAttribute : HandleErrorAttribute 
    { 
     public override void OnException(ExceptionContext context) 
     { 
      // Write to log code 
      base.OnException(context); 
     } 
    } 

और अद्यतन RegisterGlobalFilters और विधि सजावट: मैं प्रवेश कोड के साथ एक कस्टम HandleError विशेषता बना। यह आम तौर पर काम करता है लेकिन विधि है कि MyHandleError(View = "SpecialError")] OnException विधि के साथ सजाया गया है भीतर एक अपवाद तब होता है जब दो बार कहा जाता है। मैं मूल रूप से माना जाता है कि सजा इस विशेषता के साथ विधि वैश्विक हैंडलर अधिक्रमण, लेकिन ऐसा लगता है कि यह बस में जोड़ा जाता है (जो और अधिक समझ में आता है, लेकिन यह मैं क्या चाहते हैं नहीं है)। ऑनएक्सप्शन को दो बार कॉल करके, एक ही अपवाद दो बार लॉग होता है जो नहीं होना चाहिए। मुझे नहीं लगता कि OnException बुलाया जा रहा है दो बार क्योंकि यह एक कस्टम विशेषता है - मेरा मानना ​​है कि यह भी मानक HandleError विशेषता के साथ होता है, यह बस अब दिख रहा है के रूप में मैं इसके बारे में एक रिकॉर्ड बनाया है।

अंत में, मैं, सभी बिना क्रिया अपवाद (एक बार) लॉग इन करने की है, जबकि [HandleError] द्वारा की पेशकश की सुविधाओं को बनाए रखना विशेष रूप से विशेष विधि अपवाद के लिए अलग-अलग दृश्यों की स्थापना करना चाहते हैं। क्या ऐसा करने का कोई साफ तरीका है?

उत्तर

9

मेरा मानना ​​है कि मैं अपने आप को इस के लिए एक साफ समाधान मिल गया। विस्तार से हैंडलर एक अच्छा विचार की तरह लग रहा था लेकिन अब मुझे लगता है कि यह गलत दिशा में एक कदम था। मैं किसी भी त्रुटि को अलग-अलग संभाल नहीं लेना चाहता था, हैंडलरर ने उन्हें उठाए जाने से पहले एक बार लॉग इन करने के लिए अपवाद लिखें। इस वजह से, डिफॉल्ट हैंडलरर को जगह में छोड़ा जा सकता है। OnException कई बार कहा जा सकता है, यह HandleErrorAttribute के मानक लागू करने में पूरी तरह से सौम्य प्रतीत होता है।

इसके बजाय मैं एक अपवाद लॉगिंग फ़िल्टर बनाया:

public class LoggedExceptionFilter : IExceptionFilter 
    { 
     public void OnException(ExceptionContext filterContext) 
     { 
      // logging code 
     } 
    } 

यह FilterAttribute से विरासत भी रूप में यह सिर्फ HandleErrorAttribute साथ RegisterGlobalFilters भीतर एक बार पंजीकृत है की जरूरत नहीं है।

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new LoggedExceptionFilter()); 
     filters.Add(new HandleErrorAttribute()); 
    } 

यह अनुमति देता है अपवाद मानक [HandleError] सुविधाओं

+1

धन्यवाद! यह मेरे लिए भी काम किया। – abjbhat

+0

हाय, अच्छा समाधान, लेकिन आप कक्षा/विधि नाम जैसे अपवाद के स्रोत से अधिक जानकारी कैसे प्राप्त कर सकते हैं? – Patrick

2

आप एक कस्टम IFilterProvider जो अगर फिल्टर पहले से ही है कि कार्रवाई करने के लिए लागू किया गया है की जाँच करेगा बना सकते हैं: बजाय GlobalFilterCollection के साथ अपने फिल्टर के पंजीकरण की

public class MyFilterProvider : IFilterProvider 
{ 
    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) 
    { 
     if (!actionDescriptor.GetFilterAttributes(true).Any(a => a.GetType() == typeof(MyHandleErrorAttribute))) 
     { 
      yield return new Filter(new MyHandleErrorAttribute(), FilterScope.Global, null); 
     } 
    } 
} 

फिर, आप Application_Start() में अपने फ़िल्टर प्रदाता रजिस्टर होगा

FilterProviders.Providers.Add(new MyFilterProvider()); 

वैकल्पिक रूप से (@Mark क्या प्रस्तावित के समान) आप स्पष्ट रूप सेसेट कर सकते हैं ExceptionContext

public class MyHandleErrorAttribute : HandleErrorAttribute 
{ 
    public override void OnException(ExceptionContext context) 
    { 
     if(context.ExceptionHandled) return; 

     // Write to log code 
     base.OnException(context); 
     context.ExceptionHandled = true; 
    } 
} 
3

0 संपत्ति इस प्रयास करें,

public class MyHandleErrorAttribute : HandleErrorAttribute 
{ 
    public override void OnException(ExceptionContext context) 
    { 
     var exceptionHandled = context.ExceptionHandled; 

     base.OnException(context);       

     if(!exceptionHandled && context.ExceptionHandled) 
      // log the error. 
    } 
} 
+0

क्या एक आदर्श चाल है। धन्यवाद यह मेरे लिए ठीक काम करता है। धन्यवाद – mayk

-1

मैं वास्तव में दो बार फायरिंग से OnException विधि रखने का हल पाया बदले बिना बड़े करीने से लॉग इन करने की। आप FilterConfig.RegisterGlobalFilters में उपयोग कर रहे हैं() विधि, टिप्पणी-आउट HandleErrorAttribute का पंजीकरण:

public class FilterConfig 
{ 
    public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     //filters.Add(new HandleErrorAttribute()); 
    } 
} 

वास्तव में, मैं भी इस्तेमाल किया यह पंजीकरण किए बिना निर्मित HandleErrorAttribute, और यह ठीक काम किया। मुझे केवल कस्टम त्रुटियों को चालू करने की आवश्यकता है:

<system.web> 
    <customErrors mode="On" /> 
</system.web> 
+0

शायद आपको प्रश्न फिर से पढ़ना चाहिए। वह एक ही समय में दोनों का उपयोग करना चाहता है। –

संबंधित मुद्दे