Handling Unhandled Exceptions in ASP.NET UserControls

I dynamically load user controls by adding them to a collection of web form controls.

I want to hide user controls if they raise an unhandled exception when rendering.

So, I tried to connect to the Error event of each UserControl, but it seems that this event never fires for UserControls, as for the page class.

Was there some kind of search engine, and that doesn't seem promising. Any ideas here?

+4
source share
7 answers

mmilic, following from your answer to the previous idea.

No additional logic required! This is that you are not doing anything with the classes in question, just wrapping them in some kind of instantiation bubble! :)

OK, I was going to just point out the point, but I wanted to see this work for myself, so I put together very crude code, but the concept is there and it seems to work.

APOLOGIES FOR LONG MAIL

Safeloader

Basically it will be the β€œbubble” that I mentioned. It will receive HTML controls, catching any errors that occur during 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>"; } } } 

And some controls ..

Well, I just scoffed at two control elements here, one will throw another, there will be garbage. Here, I don't hold shit. They will be replaced by your user controls.

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

Page

OK, so let's look at the test page. Here I just create controls, grab their html and display it, I will follow the thoughts on supporting designers, 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); } 

Thoughts

OK, I know what you think, "these controls are programmed, and as for the support of designers? I spent many hours making these controls pleasant for the designer, now you mess with my mojo."

OK, so I really haven’t tested it yet (maybe I'll do it in a minute!), But the idea here is to override the CreateChildControls method for the page and take an instance of each control added to the form and run it SafeLoader. If the code passes, you can add it to the Controls collection as usual, if not, then you can create erroneous literals or something else, up to your friend.

Finally..

Again, sorry for the long post, but I wanted to get the code here so we can discuss it :) Hope this helps demonstrate my idea :)

Update

Tested by inserting the control into the constructor and overriding the CreateChildControls method with this, it works fine, it may take some cleanup to improve the situation, but I'll leave it to you;)

 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 it!

+12
source

This is an interesting problem. I'm still pretty fresh when it comes to user controls, etc., but here are my thoughts (feel free to comment / correct people!) .. (I, like, think / wrote loudly here!)

  • If an error occurred during the rendering, in some cases it would not be too late? (since some HTML controls may have already been submitted to Writer and are being output).
  • Therefore, it would not be better if the Render method for user control were processed, but instead of passing it a link to the Live HtmlTextWriter, you pass your own traps of any Exceptions raised in this little security bubble if everything goes ok, then you pass your resulting HTML to the actual HtmlTextWriter?
  • This logic can probably be ported to a common wrapper class that you would use to dynamically load / render controls at runtime.
  • If any errors occur, you have all the necessary information at your disposal! (e.g., reference links, etc.).

Just my thoughts, flame away !: D;)

+4
source

Depending on where your errors occur, you can do something like ...

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

It then inherits SilentErrorControl instead of UserControl.

+1
source

Global.asax and Application_Error?

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

Or the Page_Error event on a separate page:

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

In addition, Karl Segin (Hi Karl!) Received a message instead of HttpHandler:

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

(You do not know what permission to play it, but if you want to write an answer, you got my Upvote ☺)

0
source

How about adding a new subclass of UserControl that handles errors in its visualization and loading methods (so that they hide as you wish) and then inherit from this for your custom controls?

0
source

I'm not sure I understand your answer . How do you upload your controls and add them to your collection of controls?

In this, the entire bit is added to the "Update" section. You have the opportunity to use SafeLoader, wherever you are.

I'm not sure why you feel that you do not have access / control over Html? The goal of SafeLoader is that you don’t like what html is, you are just trying to "output" the control (within the "bubble") and determine if it loads OK in its current state.

If this is the case (i.e., html is returned), you can do anything with it, output html, add a control to the collection of controls, whatever!

If not, then again you can do what you like, visualize the error message, throw a custom exception .. The choice is yours!

Hope this helps you clarify the situation, if not, then please shout :)

0
source

I used the @Keith approach, but the problem is that the control is processed until Exception is thrown, which may lead to the opening of HTML tags. I also provide exception information in the control if in debug mode.

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

Source: https://habr.com/ru/post/1276329/


All Articles