Domanda

Sto caricamento dinamico di controlli utente in aggiunta ai Controlli di raccolta del modulo web.

Mi piacerebbe nascondere i controlli utente se sono causa di un'eccezione non gestita durante il rendering.

Così, ho cercato di aggancio per l'evento di Errore di ogni controllo utente, ma sembra che questo evento non viene generato per i controlli utente come si fa per classe Page.

Fatto qualche googling intorno e non sembra promettente.Tutte le idee qui?

È stato utile?

Soluzione

mmilic, a seguito la tua risposta a mio idea precedente..

Nessuna logica aggiuntiva necessaria!Questo è il punto, il non fare nulla per le classi in questione, solo che li avvolge in alcuni istanza bubble-wrap!:)

OK, volevo solo punto, ma ho voluto vedere questo lavoro per me, così ho messa insieme alcuni molto ruvida di codice, ma il concetto c'è e sembra funzionare.

SCUSATE PER IL LUNGO POST

Il SafeLoader

Questo sarà essenzialmente essere la "bolla" che ho citato..Si otterrà i controlli HTML, la cattura di eventuali errori che si verificano durante il Rendering.

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

E Alcuni Controlli..

Ok ho appena deriso insieme a due controlli di qui, la volontà di lanciare il rendering spazzatura.Il punto, qui, non dare una merda.Questi potranno essere sostituiti con controlli personalizzati..

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

La Pagina

OK, quindi, consente di guardare la pagina "test"..Qui ho semplicemente creare un'istanza di controlli, afferrare la loro html e di uscita, io l'seguire con i pensieri su supporto per la progettazione, ecc..

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

Pensieri

OK, so cosa stai pensando "questi controlli sono istanziati a livello di programmazione, che cosa circa il supporto per la progettazione?Ho trascorso impazzendo ore raggiungere questi controlli bello per il designer, ora stai prendendo in giro con la mia mojo".

OK, quindi non ho davvero provato questo, ma (probabilmente farà in un min!) ma l'idea qui è di sovrascrivere il metodo CreateChildControls per la pagina, e prendere l'istanza di ogni maggiore controllo sulla forma e correre attraverso la SafeLoader.Se il codice passa, si può aggiungere all'insieme di Controlli, come è normale, se non, allora si può creare errati valori letterali o qualcosa del genere, a voi il mio amico.

Finalmente..

Di nuovo, scusate per il post lungo, ma ho voluto ottenere il codice qui in modo che possiamo discutere di questo :) Spero che questo aiuta a dimostrare la mia idea :)

Aggiornamento

Testato per piacere un controllo sulla progettazione e l'override del metodo CreateChildControls con questo, funziona bene, può essere necessario un po di pulizia per rendere le cose un aspetto migliore, ma lascio a voi ;)

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

Enjoy!

Altri suggerimenti

Questo è un problema interessante..Io sono ancora piuttosto fresco quando si tratta di controlli personalizzati ecc, ma qui sono i miei pensieri (sentitevi liberi di commentare/persone corrette!)..(Io sono un pò pensare/scrittura ad alta voce qui!)

  • Se si verifica un errore durante il rendering, in alcuni casi, non sarebbe troppo tardi?(dal momento che alcuni dei controlli HTML potrebbe essere già stato inviato lo Scrittore e uscita).
  • Pertanto, non sarebbe meglio spostare il controllo utente del metodo Render, ma anziché passare il riferimento al "Live" HtmlTextWriter, si passa il proprio, di intercettare eventuali Eccezioni sollevate in questo po ' di sicurezza "bolla", se tutto va bene, poi passare il codice HTML risultante per l'effettivo HtmlTextWriter?
  • Questa logica, probabilmente, potrebbe essere legata ad una generica classe wrapper che è possibile utilizzare per caricare in modo dinamico/rendere i controlli in fase di esecuzione..
  • Se gli errori si verificano, si hanno tutte le informazioni di cui hai bisogno a disposizione!(io.e riferimenti di controllo, ecc).

Solo i miei pensieri, fiamma di distanza!:D ;)

A seconda del paese in cui si verificano errori si può fare qualcosa di simile...

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

Quindi ereditare SilentErrorControl invece di UserControl.

Globale.asax e Application_Error?

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

O l'Evento Page_Error su una singola Pagina solo:

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

Inoltre, Karl Seguin (Ciao Karl!) era un Post sull'uso di HttpHandler invece:

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

(Non sono sicuro di quello che l'autorizzazione a riprodurlo, ma se si vuole scrivere una risposta, hai la mia Upvote ☺)

Che ne dici di aggiungere una nuova sub-classe UserControl che errore-gestisce il rendering e metodi di caricamento (in modo da nascondere, come si vuole) e quindi eredita da quella per il tuo utente controlli?

Io non sono sicuro di aver capito la tua risposta..Come stai caricamento di controlli e di aggiungerli al vostro insieme di controlli?

Che è stato il punto di tutta la bit aggiunto in "Aggiornamento" la sezione..Hai la possibilità di utilizzare il SafeLoader ovunque tu per favore.

Io non sono sicuro perché credi di non avere accesso/controllo sul codice Html?L'obiettivo del SafeLoader è che tu non cura ciò che l'html è, è semplicemente provare e "uscita", il controllo (all'interno della "bolla") e determinare se si carica su OK nel suo stato attuale.

Se lo fa (cioèil codice html viene restituito) e poi puoi fare quello che vuoi con esso, l'output html, aggiungere il controllo l'insieme di controlli, a prescindere!

Se non, poi di nuovo, si può fare ciò che ti piace, il rendering di un messaggio di errore, lanciare un'eccezione personalizzata..La scelta è vostra!

Spero che questo aiuta a chiarire le cose per voi, se non, allora si prega di gridare :)

Ho usato @Keith approccio, ma il problema è che il controllo è reso up fino a quando viene generata l'Eccezione, potenzialmente con conseguente aprire i tag HTML.Anche io sto rendering eccezione informazioni in Controllo, se in modalità di Debug.

  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));
     }
  }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top