 <p>Ok, so I figured out a work around. Instead of using the <code>UserControl</code> object, I use the <code>Page</code> object to render the control as it will render the server controls properly. After this, I had to wrap my html code in a <code>form</code> object with <code>runat="server"</code>. Now I have no issues getting it.</p> <p>Downside is that I still have to make a call do databind the repeater as the <code>Load</code> event is never raised.</p> <p><strong>Control:</strong></p> <pre><code>&lt;form runat="server"&gt; &lt;table id="user-comments"&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;Created On&lt;/th&gt; &lt;th&gt;By&lt;/th&gt; &lt;th&gt;Comment&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;asp:Repeater ID="commentsRepeater" runat="server"&gt; &lt;ItemTemplate&gt; &lt;tr class="user-comment"&gt; &lt;td&gt;&lt;%#Eval("ReviewedOn")%&gt;&lt;/td&gt; &lt;td&gt;&lt;%#Eval("Reviewer")%&gt;&lt;/td&gt; &lt;td&gt;&lt;%#Eval("Comment")%&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/ItemTemplate&gt; &lt;/asp:Repeater&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;/form&gt; </code></pre> <p><strong>Code-behind</strong>:</p> <pre><code> public partial class UserComments : System.Web.UI.UserControl { public List&lt;CallReview&gt; Comments; public void BindComments() { commentsRepeater.DataSource = Comments; commentsRepeater.DataBind(); } } </code></pre> <p><strong>Code to render the control and get the raw HTML:</strong></p> <pre><code>//Will be used to load the control var loader = new Page(); var ctl = (UserComments)loader.LoadControl("~/Controls/UserComments.ascx"); //Set the comments property of the control ctl.Comments = _callAdapter.GetCallComments(callId); ctl.BindComments(); //Create streams the control will be rendered to TextWriter txtWriter = new StringWriter(); HtmlTextWriter writer = new HtmlTextWriter(txtWriter); //Render the control and write it to the stream ctl.RenderControl(writer); //Return the HTML return txtWriter.ToString(); </code></pre>