views:

785

answers:

2

I'm referencing the article reference

To create a UserControl dynamically and pass it back to a page via jQuery.

When I just do a simple text in the UserControl "Hello World" everything works great... however, when I tried putting interactive controls on the control, I got the following message in my WebMethod (so the jQuery call stuff is irrelevant) (further testing showed that textboxes, and buttons cause the issue, but not labels)

Error executing child request for handler 'System.Web.UI.Page'

here's the webmethod:

[WebMethod]
public static string GetCtrl(string cname)
{
    StringWriter sw = new StringWriter();

    Page p = new Page();
    Control c = p.LoadControl("~/Controls/" + cname);
    p.Controls.Add(c);

    try
    {
        HttpContext.Current.Server.Execute(p, sw, false);
    }
    catch (Exception err)
    {
        return err.Message;
    }
    sw.Close();

    return sw.ToString();
}

The exception is happening during the Server.Execute call.

A solution may not be possible, I'd just like to know why interactive controls cause this.

EDIT: Taking advice below I looked deeper and found the inner exception said something to the effect that it must be within a form tag marked with runat="server", while I'm displaying this control on a aspx page within the form tag... my guess is that there's got to be some sort of 'asp.net magic' connection there for the control to operate... regardless, it'd be nice to know how to render a page with controls on it anyway (even if it wasn't usable in this situation)

So I looked at the output of the above code and for those curious:

<span id="ctl00_lbl1">abc: </span>

So the control is rendering properly (with just the label id='lbl1') on the page, however, the control is itself rendered, and the page content is not there at all... Is there a way to generate the page source as well? (I must not understand the way the Server.Execute function works)

A: 

I would try rendering the control and sending that string back...

Control ctrl;
StringBuilder sb = new StringBuilder();
StringWriter tw = new StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(tw);

ctrl.RenderControl(hw);
return sb.ToString();
George
@George, would you also implement using statements, considering most of those objects you're creating implement IDisposable?
John Saunders
Good idea using the RenderControl method, unfortunately this doesn't cause the control to go through a page lifecycle (so the Page_Load event for instance, doesn't get called)
Mike
The control has it's own lifecycle it will go through. If you had code in the Page the object is contained in move it to the Load event.http://msdn.microsoft.com/en-us/library/aa719775(VS.71).aspx
George
+1  A: 

I'd start by narrowing down the problem. For instance, what happens if you leave off the

p.Controls.Add(c);

What happens if you properly implement a using statement?

using (StringWriter sw = new StringWriter()) {
    // ...
    HttpContext.Current.Server.Execute(p, sw, false);
    return sw.ToString();
}

What happens, if you leave off the try/catch? It's costing you all the information in the exception other than the Message property, so why not just leave it off? Your caller might be expecting HTML in any case, so if you keep it, you might (later) want to wrap the output:

return "<p>" + ex.ToString() + "</p>";

Little by little, remove things until the problem goes away.


Based on what you learned from the InnerException, I recommend that you add an HtmlForm control to the page, then add your loaded control as a child control of the HtmlForm.

John Saunders
using statement wouldn't help anything, as it would only give me a bit of control over the cleanup and the exception is happening in the Server.Execute function before I would even consider cleaning anything up (tested just to make sure)The try/catch was put in so I could get live feedback of the message instead of just a blank screen, and give me a good place to do a debug break. (digging into my debug info a bit deeper was helpful)
Mike
I think that, without the try/catch, ASP.NET Health Monitoring would have logged the entire exception, including the InnerException that you found helpful. Proper implementation of exceptions and using statements is helpful because it allows people like me to concentrate on the real problem, and not waste time being pedantic about good practice.
John Saunders