ASP.NET UserControls में अनचाहे अपवादों को पकड़ना

मैं गतिशील रूप से उपयोगकर्ता नियंत्रण को वेब फ़ॉर्म के नियंत्रण संग्रह में जोड़ रहा हूं।

मैं उपयोगकर्ता नियंत्रण को छिपाना चाहता हूं अगर वे प्रतिपादन करते समय एक अनचाहे अपवाद का कारण बनते हैं।

इसलिए, मैंने प्रत्येक उपयोगकर्ता नियंत्रण की त्रुटि घटना को हुक करने की कोशिश की लेकिन ऐसा लगता है कि यह घटना उपयोगकर्ता नियंत्रण के लिए कभी भी आग लगती है क्योंकि यह पृष्ठ वर्ग के लिए होती है।

क्या कुछ आसपास घूमते थे और यह आशाजनक प्रतीत नहीं होता है। यहां कोई विचार है?

0
ro fr bn

7 उत्तर

Global.asax और Application_Error?

http://www.15seconds.com/issue/030102.htm

या पेज_इरर इवेंट केवल एक व्यक्तिगत पृष्ठ पर:

http://support.microsoft.com/kb/306355

void Page_Load(object sender, System.EventArgs e)
{
    throw(new ArgumentNullException());
}

public void Page_Error(object sender,EventArgs e)
{
    Exception objErr = Server.GetLastError().GetBaseException();
    string err =    "Error Caught in Page_Error event

" + "
Error in: " + Request.Url.ToString() + "
Error Message: " + objErr.Message.ToString()+ "
Stack Trace:
" + objErr.StackTrace.ToString(); Response.Write(err.ToString()); Server.ClearError(); }

इसके अलावा, कार्ल सेगुइन (हाय कार्ल!) के बजाय HttpHandler का उपयोग करने पर एक पोस्ट था:

http://codebetter.com/blogs/karlseguin/archive/ 2006/06/12/146356.aspx

(सुनिश्चित नहीं है कि इसे पुन: उत्पन्न करने की अनुमति क्या है, लेकिन यदि आप एक उत्तर लिखना चाहते हैं, तो आपको मेरा उपरोक्त मिला?)

0
जोड़ा

UserControl का एक नया उप-वर्ग जोड़ने के बारे में, जो इसके रेंडर और लोड विधियों को त्रुटि-संभालता है (ताकि वे आपकी इच्छानुसार छुपाएं) और उसके बाद आपके उपयोगकर्ता नियंत्रण के लिए विरासत में हो?

0
जोड़ा

आपकी त्रुटियां कहां हो रही हैं इसके आधार पर आप कुछ ऐसा कर सकते हैं ...

public abstract class SilentErrorControl : UserControl
{
    protected override void Render( HtmlTextWriter writer )
    {
        //call the base's render method, but with a try catch
        try { base.Render( writer ); }
        catch ( Exception ex ) { /*do nothing*/ }
    }
}

फिर UserControl के बजाय SilentErrorControl का उत्तराधिकारी।

0
जोड़ा

यह एक दिलचस्प समस्या है .. जब भी कस्टम नियंत्रण आदि की बात आती है, तब भी मैं बहुत ताजा हूं, लेकिन यहां मेरे विचार हैं (लोगों को टिप्पणी करने/सही करने के लिए स्वतंत्र महसूस करें!) .. (मैं थोड़ी सोच रहा हूं/यहां जोर से लिख रहा हूं!)

  • यदि प्रतिपादन के दौरान कोई त्रुटि होती है, तो कुछ मामलों में, क्या यह बहुत देर हो चुकी नहीं है? (चूंकि कुछ नियंत्रण HTML पहले ही लेखक और आउटपुट पर भेजे जा चुके हैं)।
  • इसलिए, उपयोगकर्ता नियंत्रण की रेंडर विधि को लपेटना सबसे अच्छा नहीं होगा, बल्कि इसे "लाइव" HtmlTextWriter के संदर्भ को पारित करने के बजाय, आप स्वयं को पास करेंगे, इस छोटी सुरक्षा "बबल" में उठाए गए किसी भी अपवाद को फंसाने के लिए, यदि सब ठीक हो जाता है, फिर आप अपने परिणामी HTML को वास्तविक HtmlTextWriter पर पास करते हैं?
  • यह तर्क शायद एक सामान्य रैपर वर्ग में फंस सकता है जिसका उपयोग आप रन टाइम पर नियंत्रण को गतिशील रूप से लोड/प्रस्तुत करने के लिए करेंगे ..
  • यदि कोई त्रुटियां होती हैं, तो आपके पास अपने निपटारे में आवश्यक सारी जानकारी है! (यानी नियंत्रण संदर्भ आदि)।

बस मेरे विचार, दूर लौट जाओ! : डी;)

0
जोड़ा

mmilic, आपकी प्रतिक्रिया से मेरे स्पष्ट विचार ..

कोई अतिरिक्त तर्क की आवश्यकता नहीं है! यही बात है, आप प्रश्नों के वर्गों के लिए कुछ भी नहीं कर रहे हैं, बस उन्हें कुछ तात्कालिकता बुलबुला-लपेटो में लपेटो! :)

ठीक है, मैं सिर्फ बुलेट प्वाइंट पर जा रहा था लेकिन मैं अपने लिए यह काम देखना चाहता था, इसलिए मैंने कुछ बहुत किसी न किसी कोड को एक साथ जोड़ दिया लेकिन अवधारणा वहां है और ऐसा लगता है।

लंबे पद के लिए अपॉजिज

सेफलोडर

यह मूल रूप से "बबल" होगा जिसका मैंने उल्लेख किया है .. इसे नियंत्रण एचटीएमएल मिलेगा, जो रेंडरिंग के दौरान होने वाली किसी भी त्रुटि को पकड़ लेगा।

public class SafeLoader
{
    public static string LoadControl(Control ctl)
    {
       //In terms of what we could do here, its down
       //to you, I will just return some basic HTML saying
       //I screwed up.
        try
        {
           //Get the Controls HTML (which may throw)
           //And store it in our own writer away from the
           //actual Live page.
            StringWriter writer = new StringWriter();
            HtmlTextWriter htmlWriter = new HtmlTextWriter(writer);
            ctl.RenderControl(htmlWriter);

            return writer.GetStringBuilder().ToString();
        }
        catch (Exception)
        {
            string ctlType = ctl.GetType().Name;
            return "" + 
                "Rob + Controls = FAIL (" + 
                ctlType + " rendering failed) Sad face :(";
        }
    }
}

और कुछ नियंत्रण ..

ठीक है, मैंने अभी दो नियंत्रणों को एक साथ मजाक कर दिया है, एक दूसरे को फेंक देगा जंक प्रस्तुत करेगा। यहां इंगित करें, मैं एक बकवास नहीं देता हूं। इन्हें आपके कस्टम नियंत्रण से बदल दिया जाएगा ..

BadControl

public class BadControl : WebControl
{
    protected override void Render(HtmlTextWriter writer)
    {
        throw new ApplicationException("Rob can't program controls");
    }
}

GoodControl

public class GoodControl : WebControl
{
    protected override void Render(HtmlTextWriter writer)
    {
        writer.Write("Holy crap this control works");
    }
}

पन्ना

ठीक है, तो चलिए "टेस्ट" पेज देखें। यहां मैं बस नियंत्रण को तुरंत चालू करता हूं, अपना एचटीएमएल लेता हूं और इसे आउटपुट करता हूं, मैं डिजाइनर समर्थन आदि पर विचारों का पालन करता हूं ..

पेज कोड-पीछे

    protected void Page_Load(object sender, EventArgs e)
    {
       //Create some controls (BadControl will throw)
        string goodHtml = SafeLoader.LoadControl(new BadControl());
        Response.Write(goodHtml);

        string badHtml = SafeLoader.LoadControl(new GoodControl());
        Response.Write(badHtml);
    }

विचार

ठीक है, मुझे पता है कि आप क्या सोच रहे हैं, "इन नियंत्रणों को प्रोग्रामेटिक रूप से तत्काल किया जाता है, डिजाइनर समर्थन के बारे में क्या? मैंने डिजाइनर के लिए इन नियंत्रणों को अच्छा बनाने में घंटों का समय बिताया, अब आप मेरे मोजो के साथ गड़बड़ कर रहे हैं"।

OK, so I havent really tested this yet (probably will do in a min!) but the idea here is to override the CreateChildControls method for पन्ना, and take the instance of each control added on the form and run it through सेफलोडर. If the code passes, you can add it to the Controls collection as normal, if not, then you can create erroneous literals or something, up to you my friend.

आखिरकार..

दोबारा, लंबे पद के लिए खेद है, लेकिन मैं यहां कोड प्राप्त करना चाहता था ताकि हम इस पर चर्चा कर सकें :) मुझे उम्मीद है कि यह मेरे विचार को प्रदर्शित करने में मदद करता है :)

अद्यतन करें

डिजाइनर पर नियंत्रण को चकित करके और CreateChildControls विधि को ओवरराइड करके परीक्षण किया गया है, ठीक काम करता है, चीजों को बेहतर दिखने के लिए कुछ साफ करने की आवश्यकता हो सकती है, लेकिन मैं इसे आपके पास छोड़ दूंगा;)

protected override void CreateChildControls()
{
   //Pass each control through the Loader to check
   //its not lame
    foreach (Control ctl in Controls)
    {
        string s = SafeLoader.LoadControl(ctl);
       //If its bad, smack it downnnn!
        if (s == string.Empty)
        {
            ctl.Visible = false;//Prevent Rendering
            string ctlType = ctl.GetType().Name;
            Response.Write("Problem Occurred Rendering " + 
                ctlType + " '" + ctl.ID + "'.");
        }
    }
}

का आनंद लें!

0
जोड़ा

मुझे यकीन नहीं है कि मैं आपकी प्रतिक्रिया समझता हूं .. आप कैसे लोड हो रहे हैं आपके नियंत्रण और उन्हें अपने नियंत्रण संग्रह में जोड़ना?

"अद्यतन" खंड में जोड़े गए बिट का पूरा बिंदु था .. जहां भी आप कृपया SafeLoader का उपयोग करने के लिए लचीलापन रखते हैं।

मुझे यकीन नहीं है कि आपको क्यों लगता है कि आपके पास एचटीएमएल पर पहुंच/नियंत्रण नहीं है? सेफलोडर का लक्ष्य यह है कि आप देखभाल html क्या है, आप बस नियंत्रण और "आउटपुट" को नियंत्रित करते हैं ("बबल" के भीतर) और यह निर्धारित करते हैं कि यह वर्तमान स्थिति में ठीक है या नहीं।

अगर ऐसा होता है (यानी एचटीएमएल वापस आ गया है) तो आप जो भी चाहते हैं उसे कर सकते हैं, एचटीएमएल आउटपुट कर सकते हैं, नियंत्रण संग्रह में नियंत्रण जोड़ सकते हैं, जो भी हो!

यदि नहीं, तो फिर, आप जो भी चाहें कर सकते हैं, एक त्रुटि संदेश प्रस्तुत कर सकते हैं, एक कस्टम अपवाद फेंक सकते हैं .. पसंद तुम्हारा है!

मुझे उम्मीद है कि इससे आपके लिए चीजों को स्पष्ट करने में मदद मिलेगी, यदि नहीं, तो कृपया चिल्लाओ :)

0
जोड़ा

मैंने @ कीथ के दृष्टिकोण का उपयोग किया, लेकिन समस्या यह है कि अपवाद को फेंकने तक नियंत्रण प्रदान किया जाता है, संभावित रूप से खुले HTML टैग के परिणामस्वरूप। यदि डीबग मोड में मैं नियंत्रण में अपवाद जानकारी भी प्रस्तुत कर रहा हूं।

  protected override void Render(System.Web.UI.HtmlTextWriter writer)
  {
     try
     {
       //Render the module to a local a temporary writer so that if an Exception occurs
       //the control is not halfway rendered - "it is all or nothing" proposition
        System.IO.StringWriter sw = new System.IO.StringWriter();
        System.Web.UI.HtmlTextWriter htw = new System.Web.UI.HtmlTextWriter(sw);
        base.Render(htw);

       //We made it!  Copy the Control Render over
        writer.Write(sw.GetStringBuilder().ToString());
     }
     catch (System.Exception ex)
     {
        string message = string.Format("Error Rendering Control {0}\n", ID);
        Log.Error(message, ex);
        if (Page.IsDebug)
           writer.Write(string.Format("{0}
Exception:
{1}\n{2}
", message, ex.Message, ex.StackTrace)); } }
0
जोड़ा