Frage

Ich bin das dynamische laden von Benutzer-Steuerelemente hinzufügen, um die Controls-Auflistung des web-Formulars.

Ich möchte zu verstecken, Benutzersteuerelemente, wenn Sie eine unbehandelte Ausnahme beim Rendern.

So, ich habe versucht, Einhaken, um die Fehler-Ereignis jedes Benutzersteuerelement, aber es scheint, dass dieses Ereignis nie ausgelöst, die Benutzersteuerelemente, wie es für Page-Klasse.

Habe einige googeln herum, und es scheint nicht vielversprechend.Irgendwelche Ideen hier?

War es hilfreich?

Lösung

mmilic, nach Ihre Antwort zu meinem bisherige Idee..

Keine zusätzliche Logik erforderlich!Das ist der Punkt, Ihr tut nichts, um die Klassen in Frage, nur das einwickeln von Ihnen in einigen Instanziierung bubble-wrap!:)

OK, ich wollte einfach nur Punkt, aber ich wollte sehen, wie diese Arbeit für mich, so dass ich zusammen gebastelt einige sehr rau-code, aber das Konzept ist es und es scheint zu funktionieren.

ENTSCHULDIGUNG FÜR DIE LANGE POST

Die SafeLoader

Dies ist im wesentlichen die "bubble", die ich erwähnt..Es wird Holen Sie sich die HTML-Steuerelemente, fangen alle Fehler, die auftreten während der Wiedergabe.

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 "<span style=\"color: red; font-weight:bold; font-size: smaller;\">" + 
                "Rob + Controls = FAIL (" + 
                ctlType + " rendering failed) Sad face :(</span>";
        }
    }
}

Und Einige Steuerelemente..

Ok, ich habe gerade verspottet zusammen zwei Steuerelemente hier, einen werfen den anderen machen wird junk.Punkt ist hier, ich weiß nicht give a crap.Diese werden ersetzt durch benutzerdefinierte Steuerelemente..

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("<b>Holy crap this control works</b>");
    }
}

Die Seite

OK, so können Blick auf die "test" - Seite..Hier habe ich einfach instanziieren Sie die Steuerelemente, schnappen Sie sich Ihre html-und Ausgabe, Folge ich mit dem Gedanken auf designer-Unterstützung etc..

Page Code-Behind

    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);
    }

Gedanken

OK, ich weiß, was Sie denken, "diese Steuerelemente instanziiert ein Programm, was über designer-Unterstützung?Ich verbrachte freaking Stunden und immer diese Steuerelemente schön für die designer, jetzt bist du Durcheinander mit meinem mojo".

OK, also habe ich nicht wirklich getestet, aber (wahrscheinlich tun min!) aber die Idee hier ist, überschreiben die CreateChildControls-Methode für die Seite, und nehmen Sie die Instanz jedes control hat auf die form, und führen Sie es durch die SafeLoader.Wenn der code übergibt, können Sie es hinzufügen, um die Controls-Auflistung als normal, wenn nicht, dann können Sie erstellen, falsche Literale oder etwas, bis Sie, mein Freund.

Endlich..

Wieder sorry für die lange post, aber ich wollte den code hier ein, so können wir dies besprechen :) Ich hoffe, dies hilft, zeigen meine Idee :)

Update

Getestet durch die Ausdehnung einer Kontrolle auf der designer und überschreiben der CreateChildControls-Methode mit diesem, funktioniert einwandfrei, kann einige bereinigen, um die Dinge besser Aussehen, aber das überlasse ich Euch ;)

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("<b>Problem Occurred Rendering " + 
                ctlType + " '" + ctl.ID + "'.</b>");
        }
    }
}

Genießen!

Andere Tipps

Dies ist ein Interessantes problem..Ich bin noch ziemlich frisch, wenn es kommt zu benutzerdefinierte Steuerelemente usw., aber hier sind meine Gedanken (feel free to comment/korrekte Menschen!)..(Ich bin ein bisschen denken/schreiben laut hier!)

  • Wenn ein Fehler Auftritt, während das rendering, die in einigen Fällen wäre es nicht zu spät?(da einige HTML-Steuerelemente möglicherweise bereits an das Schriftsteller-und Ausgang).
  • Daher wäre es nicht am besten wickeln Sie das Benutzersteuerelement die Render-Methode, aber anstatt es den Verweis auf die "Live" - HtmlTextWriter, übergeben Sie Ihre eigenen, trap Ausnahmen die in dieser wenig Sicherheit "Blase", wenn alles gut geht, Sie dann an Ihre resultierende HTML, um die tatsächliche HtmlTextWriter?
  • Diese Logik könnte wohl sein, schlang sich um einen generischen wrapper-Klasse, die Sie verwenden würden, um dynamisch zu laden/stellt die Steuerelemente zur Laufzeit..
  • Wenn Fehler auftreten, müssen Sie alle Informationen die Sie benötigen zur Verfügung!(ich.e Steuerelement-Referenzen usw.).

Nur meine Gedanken, Flammen fern!:D ;)

Je nachdem, wo Ihre Fehler auftreten, können Sie etwas tun wie...

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*/ }
    }
}

Dann Erben SilentErrorControl anstelle von UserControl.

Global.asax und Application_Error?

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

Oder das Ereignis page_error auf ein Event auf einer einzelnen Seite nur:

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 =    "<b>Error Caught in Page_Error event</b><hr><br>" + 
                    "<br><b>Error in: </b>" + Request.Url.ToString() +
                    "<br><b>Error Message: </b>" + objErr.Message.ToString()+
                    "<br><b>Stack Trace:</b><br>" + 
                      objErr.StackTrace.ToString();
    Response.Write(err.ToString());
    Server.ClearError();
}

Auch Karl Seguin (Hi Karl!) hatte einen Beitrag über die Verwendung HttpHandler statt:

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

(Nicht sicher, was die Genehmigung zu reproduzieren, aber wenn Sie wollen, um zu schreiben, eine Antwort, die Sie bekam mein Upvote ☺)

Wie über das hinzufügen einer neuen sub-Klasse von UserControl, dass Fehler-Griffe, die render-und Last Methoden (so dass Sie sich verstecken, wie Sie möchten) und dann die von, die für Ihre Benutzer-Steuerelemente?

Ich bin nicht sicher, ich verstehe Ihre Antwort..Wie sind Sie mit laden Sie Ihre Steuerelemente und hinzufügen zu Ihrer Sammlung controls?

Das war der springende Punkt, von dem etwas Hinzugefügt, in dem "Abschnitt" Update"..Sie haben die Flexibilität, die SafeLoader wo auch immer Sie bitte.

Ich bin nicht sicher, warum Sie glauben, Sie haben keinen Zugriff oder Kontrolle über die Html?Das Ziel der SafeLoader ist, dass Sie nicht Pflege was html ist, können Sie einfach versuchen, "output" für die Kontrolle (innerhalb der "bubble") und bestimmen Sie, ob es geladen OK in seinem aktuellen Zustand.

Wenn es gilt (D. H.der html-Code wird zurückgegeben), dann kannst du machen, was du willst es, die Ausgabe der html-fügen Sie das Steuerelement auf die controls-Auflistung, was auch immer!

Wenn nicht, dann wieder, Sie können tun, was Sie möchten, machen eine Fehlermeldung, werfen Sie eine benutzerdefinierte Ausnahme..Sie haben die Wahl!

Ich hoffe, dies hilft bei der Klärung, Dinge für Sie, wenn nicht, dann bitte Schreien Sie :)

Ich benutzte @Keith ' s Ansatz, aber das problem ist, dass das Steuerelement gerendert wird, bis die Exception geworfen wird, die potenziell in offenen HTML-tags.Ich bin auch rendering Ausnahme Informationen in die Steuerung, wenn im Debug-Modus.

  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}<br>Exception:<br><pre>{1}\n{2}</pre>", message, ex.Message, ex.StackTrace));
     }
  }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top