'getting error 'must be placed inside a form tag with runat=server', but it is

I'm getting the above error message. However, the page in question does indeed have a tag with runat="server" attribute on it (at design time) and the control is inside it. If I run the project, and view source, that attribute appears to be gone (not sure if that part is normal or what's causing it if it's not).

The error pops when I try to run RenderControl method. The page loads fine to begin with. Any ideas?

<form id="form1" runat="server">
<div id="hiddenMVR" runat="server" style="display:block;">
 // lots of other controls in here removed for brevity
</div>
</form>

Code behind:

            StringBuilder stringBuilder = new StringBuilder();
            StringWriter stringWriter = new StringWriter(stringBuilder);
            HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter);
            //error occurs on RenderControl
            this.hiddenMVR.RenderControl(htmlTextWriter);


Solution 1:[1]

Apparently the below code fixes the issue, although honestly I'm not sure why, since the original error message isn't accurate:

public override void VerifyRenderingInServerForm(Control control) 
{ 
    /* Confirms that an HtmlForm control is rendered for the specified ASP.NET server 
    control at run time. Used to avoid issue using RenderControl above */ 
}

Apparently, this overrides some built-in method that I'm not aware of, which is doing something that causes the error. Overriding it with no code prevents whatever is happening by default and thus eliminates the error.

This "fix" was mentioned in some other posts, but I didn't think it applied because the error message doesn't line up with the code.

I haven't noticed any detrimental issues from doing this.

Solution 2:[2]

Before RenderControl you need to change the type of Button, LinkButton or any other asp.net component you are using to Literal. Simplest way to do the same is to remove that control and add Literal at that place. A sample code to do the same is as below.

private void DisableControls(Control gv)
{
    Literal l = new Literal();

    for (int i = 0; i < gv.Controls.Count; i++)
    {
        if (gv.Controls[i].GetType() == typeof(Button))

        {
            l.Text = (gv.Controls[i] as Button).Text;
            gv.Controls.Remove(gv.Controls[i]);
            gv.Controls.AddAt(i, l);
        }

        if (gv.Controls[i].GetType() == typeof(LinkButton))
        {
            l.Text = (gv.Controls[i] as LinkButton).Text;
            gv.Controls.Remove(gv.Controls[i]);
            gv.Controls.AddAt(i, l);
        }

        if (gv.Controls[i].GetType() == typeof(CheckBox))
        {
            l.Text = (gv.Controls[i] as CheckBox).Text;
            gv.Controls.Remove(gv.Controls[i]);
            gv.Controls.AddAt(i, l);
        }

        if (gv.Controls[i].HasControls())
        {
            DisableControls(gv.Controls[i]);
        }
    }
}

and you can call the same using

DisableControls(listView);

before RenderControl

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Starfleet Security
Solution 2 Deepak Sahani