Seven years late, but this deserves to be shared.
The generally accepted solution - StringBuilder
into StringWriter
into HtmlWriter
into RenderControl
- is good. But there are some gotchas, which I unfortunately ran across while trying to do the same thing. Some controls will throw errors if they're not inside of a Page
, and some will throw errors if they're not inside of a <form>
with runat="server"
. The ScriptManager control exhibits both of these behaviours.
I eventually found a workaround here. The gist of it is basically just instantiating a new Page and Form before doing the writer work:
Page page = new Page();
page.EnableEventValidation = false;
HtmlForm form = new HtmlForm();
form.Name = "form1";
page.Controls.Add(form1);
MyControl mc = new MyControl();
form.Controls.Add(mc);
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
HtmlTextWriter writer = new HtmlTextWriter(sw);
page.RenderControl(writer);
return sb.ToString();
Unfortunately, this gives you more markup than you actually need (since it includes the dummy form). And the ScriptManager will still fail for some arcane reason I haven't puzzled out yet. Honestly, it's a whole lot of trouble and not worth doing; the whole point of generating controls in the code-behind is so that you don't have to fiddle around with the markup, after all.