2012-02-27 19 views
10

मेरे पास एक कस्टम HandleError विशेषता है जो एमवीसी पाइपलाइन पर त्रुटियों से संबंधित है; मेरे Global.asax पर protected void Application_Error(object sender, EventArgs e) विधि है जो पाइपलाइन के बाहर से त्रुटियों को संभालती है।एएसपी.नेट एमवीसी ग्लोबल एरर हैंडलिंग

मैं एक परिदृश्य में आया हूं जिसे मैं नहीं जानता था; DI को कार्यान्वित करने में, connectionString के लिए निर्भरता है, जिसे एप्लिकेशन कॉन्फ़िगरेशन फ़ाइल से लिया जाता है।

चूंकि कनेक्शन स्ट्रिंग अभी तक मौजूद नहीं है, नियंत्रक बनाने के दौरान एक त्रुटि उत्पन्न होती है, यह आमतौर पर Application_Error हैंडलर आग बनाता है, और एक उचित त्रुटि पृष्ठ प्रदान किया जाता है (स्ट्रिंग के रूप में आंशिक दृश्य को प्रस्तुत करने और इसे भेजने के माध्यम से "। गंभीर अपवाद"।। प्रतिक्रिया, और मामले में यह यह सिर्फ लिखते हैं विफल रहता है जवाबी कार्रवाई के लिए

इस मामले में छोड़कर, मैं fugly डिफ़ॉल्ट ASP.NET "रनटाइम त्रुटि" मौत का पीला स्क्रीन मिलता है मुझे बोलने:

रनटाइम त्रुटि

विवरण: सर्वर पर एक अनुप्रयोग त्रुटि आई। इस एप्लिकेशन के लिए वर्तमान कस्टम त्रुटि सेटिंग्स को एप्लिकेशन त्रुटि के विवरण को देखने से रोकती है।

विवरण: इस विशिष्ट त्रुटि संदेश का ब्यौरा स्थानीय सर्वर मशीन पर योग्य बनाना चाहते हैं सक्षम करने के लिए वर्तमान वेब आवेदन की जड़ निर्देशिका में स्थित एक "web.config" विन्यास फाइल के भीतर एक टैग बनाने कृपया । यह टैग पर इसके "मोड" विशेषता को "दूरस्थ रूप से" पर सेट किया जाना चाहिए। दूरस्थ मशीनों पर देखने योग्य विवरण सक्षम करने के लिए, कृपया "मोड" को "बंद" पर सेट करें।

मैं अपने customErrors में एक defaultRedirect सेट नहीं है, न ही यह, Off कर दिया क्योंकि मैं लेकिन रीडायरेक्ट करने के लिए एक ही पृष्ठ उपयोगकर्ता में है पर त्रुटियों रेंडर करने के लिए नहीं करना चाहते, एक अनावश्यक रीडायरेक्ट से परहेज है।

मैं इस तरह के परिदृश्य को कैसे संभाल सकता हूं? और यह भी कारण है कि यह इस तरह से क्यों व्यवहार करता है और नियंत्रक के बाहर किसी भी अन्य त्रुटि की तरह नहीं?

मुझे एहसास है कि यह अक्सर होने की संभावना नहीं है, लेकिन मैं वाईएसओडी को रोकने में सक्षम होना चाहता हूं (आंशिक रूप से क्योंकि मैं उस तकनीक को छिपाना चाहता हूं जिसका उपयोग मैं कर रहा हूं, लेकिन अधिकतर क्योंकि यह सुंदर नहीं है और न ही उपयोगकर्ता के अनुकूल है)

मैंने अनचाहे अपवादों के लिए एक हैंडलर पंजीकरण करने का भी प्रयास किया, लेकिन यह भी आग नहीं लगा।

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 

कोड है कि अंततः इस पैदा करता है, है:

return ConfigurationManager.ConnectionStrings[key].ConnectionString;, जहां ConnectionStrings[key]null है।

अद्यतन

यह कैसे applicaion त्रुटियों से नियंत्रित किया जाता है:

protected void Application_Error(object sender, EventArgs e) 
    { 
     this.HandleApplicationError(new ResourceController()); 
    } 

    public static void HandleApplicationError(this HttpApplication application, BaseController controller) 
    { 
     if (application == null) 
     { 
      throw new ArgumentNullException("application"); 
     } 
     if (controller == null) 
     { 
      throw new ArgumentNullException("controller"); 
     } 
     application.Response.Clear(); 
     Exception exception = application.Server.GetLastError(); 
     LogApplicationException(application.Response, exception); 
     try 
     { 
      RenderExceptionViewResponse(application, exception, controller); 
     } 
     catch (Exception exceptionRenderingView) // now we're in trouble. let's be as graceful as possible. 
     { 
      RenderExceptionTextResponse(application, exceptionRenderingView); 
     } 
     finally 
     { 
      application.Server.ClearError(); 
     } 
    } 

    private static void LogApplicationException(HttpResponse response, Exception exception) 
    { 
     if (exception is HttpException) 
     { 
      HttpException httpException = (HttpException)exception; 
      if (httpException.GetHttpCode() == (int)HttpStatusCode.NotFound) 
      { 
       _log.Debug(Resources.Error.WebResourceNotFound, httpException); 
       response.Status = Resources.Constants.NotFound; 
       return; 
      } 
     } 
     _log.Error(Resources.Error.UnhandledException, exception); 
    } 

    private static void RenderExceptionViewResponse(HttpApplication application, Exception exception, BaseController controller) 
    { 
     if (!RenderAsJsonResponse(application, Resources.User.UnhandledExceptionJson)) 
     { 
      ErrorViewModel model = WebUtility.GetErrorViewModel(exception); 
      string result = controller.RenderViewToString(Resources.Constants.ErrorViewName, model); 
      application.Response.Write(result); 
     } 
    } 

    private static void RenderExceptionTextResponse(HttpApplication application, Exception exceptionRenderingView) 
    { 
     application.Response.Clear(); 

     if (!RenderAsJsonResponse(application, Resources.User.FatalExceptionJson)) 
     { 
      application.Response.Write(Resources.User.FatalException); 
     } 
     _log.Fatal(Resources.Error.FatalException, exceptionRenderingView); 
    } 

    private static bool RenderAsJsonResponse(HttpApplication application, string message) 
    { 
     if (application.Request.IsAjaxRequest()) 
     { 
      application.Response.Status = Resources.Constants.HttpSuccess; 
      application.Response.ContentType = Resources.Constants.JsonContentType; 
      application.Response.Write(message); 
      return true; 
     } 
     return false; 
    } 

यह विशेषता मैं अपने आधार नियंत्रक को सजाने के लिए उपयोग करते हैं:

public class ErrorHandlingAttribute : HandleErrorAttribute 
{ 
    public Type LoggerType { get; set; } 

    public ErrorHandlingAttribute() 
     : this(typeof(ErrorHandlingAttribute)) 
    { 
    } 

    public ErrorHandlingAttribute(Type loggerType) 
    { 
     LoggerType = loggerType; 
    } 

    public override void OnException(ExceptionContext filterContext) 
    { 
     if (filterContext.ExceptionHandled) 
     { 
      return; 
     } 
     if (filterContext.HttpContext.Request.IsAjaxRequest()) 
     { 
      OnAjaxException(filterContext); 
     } 
     else 
     { 
      OnRegularException(filterContext); 
     } 
    } 

    internal protected void OnRegularException(ExceptionContext filterContext) 
    { 
     Exception exception = filterContext.Exception; 

     ILog logger = LogManager.GetLogger(LoggerType); 
     logger.Error(Resources.Error.UnhandledException, exception); 

     filterContext.HttpContext.Response.Clear(); 

     ErrorViewModel model = WebUtility.GetErrorViewModel(exception); 
     filterContext.Result = new ViewResult 
     { 
      ViewName = Resources.Constants.ErrorViewName, 
      ViewData = new ViewDataDictionary(model) 
     }; 
     filterContext.ExceptionHandled = true; 
    } 

    internal protected void OnAjaxException(ExceptionContext filterContext) 
    { 
     Exception exception = filterContext.Exception; 

     ILog logger = LogManager.GetLogger(LoggerType); 
     logger.Error(Resources.Error.UnhandledAjaxException, exception); 

     filterContext.HttpContext.Response.Clear(); 
     filterContext.HttpContext.Response.Status = Resources.Constants.HttpSuccess; 

     string errorMessage = WebUtility.GetUserExceptionMessage(exception, true); 

     filterContext.Result = new ExceptionJsonResult(new[] { errorMessage }); 
     filterContext.ExceptionHandled = true; 
    } 
} 

और ये मेरे customErrors है :

<customErrors mode="On" /> 

जैसा कि आप देख सकते हैं कि ये बहुत व्यापक हैं, हालांकि वे ConnectionStrings तक पहुंचने के मामले में भी आग नहीं डालते हैं, जहां ConnectionString मौजूद नहीं है; जो परेशान है।

यह किसी भी नियंत्रक में आग नियंत्रक के भीतर अपवाद या अपवाद नहीं है, इसलिए मुझे समझ में नहीं आता कि यह मामला कोई अलग क्यों है।

उत्तर

0

आप नहीं दिखाया है कि कैसे वास्तव में आप अपने Application_Error घटना में त्रुटियों संभाल रहे हैं और न ही अपनी कस्टम तो यह अनुमान लगाना क्या समस्या हो सकती है मुश्किल है HandleAttribute कार्यान्वित किया जाता है करता है। Application_Error को लागू करते समय देखने के लिए एक आम समस्या यह है कि आप कुछ त्रुटि दृश्य प्रस्तुत करते हैं जो स्वयं ही एक त्रुटि फेंकता है। उदाहरण के लिए सोचें कि एक त्रुटि दृश्य जो लेआउट पर निर्भर करता है और इस लेआउट के अंदर आप Html.Action सहायक को दूसरी क्रिया की सामग्री प्रस्तुत करने के लिए कॉल कर रहे हैं जो स्वयं डेटाबेस एक्सेस और सामान करता है। आपके त्रुटि दृश्य यथासंभव स्थिर होना चाहिए। आदर्श रूप से उन स्थितियों से बचने के लिए उनके लिए एक अलग लेआउट होना चाहिए।

मैं सुझाव दे सकता हूं कि आप त्रुटियों को संभालने के लिए following approach पर नज़र डालें।

+0

मैंने अपनी त्रुटि प्रबंधन कॉन्फ़िगरेशन के साथ अद्यतन किया। – bevacqua

+0

पार्टियल व्यू का उपयोग करने के बारे में क्या? क्या आप कृपया [एमवीसी में पार्टियल व्यू का उपयोग कर ग्लोबल एरर हैंडलिंग] पर एक नज़र डालें [http://stackoverflow.com/questions/39594409/global-error-handling-using-partialview-in-mvc)? –

7

Application_Error एएसपी.नेट वेबफॉर्म में त्रुटियों को संभालने का अनुशंसित तरीका हो सकता है। लेकिन एमवीसी में नहीं।

हमें त्रुटि फ़िल्टर मिल गए हैं जो हमारे लिए त्रुटियों का ख्याल रखते हैं। फ़िल्टर के साथ समस्या यह है कि यह केवल तब काम करता है जब नियंत्रक को बुलाया जाता है। 404 और 401 त्रुटियों (नहीं मिला और प्रमाणीकरण) और आपकी डेटाबेस कनेक्शन समस्या के लिए समस्या कौन सी है।

customErrors यहां जाने का तरीका है। मुझे नहीं लगता कि रीडायरेक्ट एक समस्या क्यों होनी चाहिए?

मैं एक ब्लॉग लेख में उचित त्रुटि हैंडलिंग के माध्यम से जा रहा हूँ: http://blog.gauffin.org/2011/11/how-to-handle-errors-in-asp-net-mvc/

+8

कस्टम त्रुटियों के लिए रीडायरेक्ट एक समस्या है क्योंकि यह मूल रूप से लापता पृष्ठ के लिए ब्राउज़र (या बॉट) पर वापस कह रहा है "हाँ यह पृष्ठ ठीक है, लेकिन कृपया अभी इस दूसरे पृष्ठ पर जाएं", तो अगला पृष्ठ कहता है "नहीं मैं" ठीक नहीं है, मैं अस्तित्व में नहीं हूं "। हालांकि आपका ब्राउज़र और बॉट (उदा। Google बॉट) दोनों लापता पृष्ठ को वास्तविक पृष्ठ के रूप में संग्रहीत करेंगे, और Google के मामले में इसे आज़माकर अनुक्रमित करना जारी रखेंगे, क्योंकि एक अस्थायी रीडायरेक्ट कहता है कि भविष्य में मूल पृष्ठ की जांच करता रहता है। यही कारण है कि अनुरोध किए गए मूल यूआरएल पर स्थिति 404 वापस करना बहुत महत्वपूर्ण है। –

+0

@jgauffin रीडायरेक्ट एक समस्या है जब त्रुटि और अपवाद हैंडलिंग के लिए ** PartialView ** का उपयोग करना पसंद करते हैं। क्या आप कृपया [एमवीसी में पार्टियल व्यू का उपयोग कर ग्लोबल एरर हैंडलिंग] पर एक नज़र डालें [http://stackoverflow.com/questions/39594409/global-error-handling-using-partialview-in-mvc)? –

0

हमारे आगंतुकों और खोज इंजनों के लिए सही होने के लिए, हम सार्थक HTTP स्थिति कोड वापस आ जाएगी अगर त्रुटियां होती हैं, हमारी साइट का सामना करना पड़। HTTP स्थिति कोड 200 को त्रुटि पर वापस करना उचित नहीं है, भले ही एक ही समय में हम एक दृश्य वापस कर दें, यह समझाते हुए कि एक त्रुटि हुई। यदि उपयोगकर्ता गलत पते (सबसे अधिक उपयोगकर्ता गलती) में टाइप करता है, तो हमें HTTP स्टेटस कोड 404 वापस करना चाहिए और वापसी या रीडायरेक्ट नहीं करना चाहिए, जहां स्टेटस कोड 200 वापस किया जाएगा।
एक छोटी और साफ सिफारिशें सारांश HERE है।

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