C# – Asp.net button object – runat server issue

asp.netbuttonc

I have a slight problem with creating a button on the server side code. I am using stringbuilder to build a table in html and I want to create a new button object and pass it into my stringbuilder object. The problem I have is my page doesn't compile when I am debugging. I want to give my button object a runat="server" property but I don't know how to.

Button add_img_popup = new Button();
            add_img_popup.Text = "Add new Image"; // text
            add_img_popup.Click += new EventHandler(addImgPopup_Click); // click event handler
            add_img_popup.Enabled = true;
            add_img_popup.ID = "btn_add_img_popup"; // programmatic id

            Page.Controls.Add(add_img_popup); // add to page controls so it renders

            st.Append("<tr>");
            st.Append("<td>");
            st.Append(add_img_popup); // pass to string builder
            st.Append("</tbody>");
            st.Append("</table>");

And the message the server gives me.


Server Error in '/' Application.

Control 'btn_add_img_popup' of type 'Button' must be placed inside a form tag with runat=server.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Web.HttpException: Control 'btn_add_img_popup' of type 'Button' must be placed inside a form tag with runat=server.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[HttpException (0x80004005): Control 'btn_add_img_popup' of type 'Button' must be placed inside a form tag with runat=server.]
System.Web.UI.Page.VerifyRenderingInServerForm(Control control) +8702387
System.Web.UI.WebControls.Button.AddAttributesToRender(HtmlTextWriter writer) +54
System.Web.UI.WebControls.WebControl.RenderBeginTag(HtmlTextWriter writer) +20
System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) +20
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +134
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
System.Web.UI.Page.Render(HtmlTextWriter writer) +29
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1266

Best Answer

It looks like you might have a couple of problems here:

Missing form tag

Ensure that your page has a form tag with 'runat=server' specified.

<form id="form1" runat="server">
    <asp:PlaceHolder ID="ph1" runat="server"/>
</form>

Code Behind:

// Create the button control
Button add_img_popup = new Button();
add_img_popup.Text = "Add new Image";

// Add it the placeholder
// (which is inside the form)
ph1.Controls.Add(add_img_popup);

Button being added to stringbuilder

Adding a control to a stringbuilder will not cause it to be rendered. You will need to render the control into a string first, using something like this:

public string RenderControl(Control ctrl) 
{
    StringBuilder sb = new StringBuilder();
    StringWriter tw = new StringWriter(sb);
    HtmlTextWriter hw = new HtmlTextWriter(tw);

    ctrl.RenderControl(hw);
    return sb.ToString();
}

You can use the RenderControl method like this:

st.Append("<tr>");
st.Append("<td>");
st.Append(RenderControl(add_img_popup));
st.Append("</tbody>");
st.Append("</table>");

Although this will render the control, you may have some trouble handling the postback event (addImgPopup_Click) as the control must be recreated on each page load.

Why do you need to add the control to the StringBuilder rather than putting the control directly on the page? There are usually better ways of achieving a goal using existing ASP.NET controls, rather than rendering something to a string first.