Cattura le eccezioni non gestite in ASP.NET controlli utente
-
08-06-2019 - |
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?
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));
}
}