GridView must be placed inside the form tag with runat = "server" even after the GridView is in the form tag
<form runat="server" id="f1"> <div runat="server" id="d"> grid view: <asp:GridView runat="server" ID="g"> </asp:GridView> </div> <asp:TextBox runat="server" ID="t" TextMode="MultiLine" Rows="20" Columns="50"></asp:TextBox> </form> Code behind:
public partial class ScriptTest : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { g.DataSource = new string[] { "a", "b", "c" }; g.DataBind(); TextWriter tw = new StringWriter(); HtmlTextWriter h = new HtmlTextWriter(tw); d.RenderControl(h); t.Text = tw.ToString(); } } Even the GridView is inside the tag using runat = "server", but I get this error.
Any clues please?
You call GridView.RenderControl(htmlTextWriter) , so an exception occurs on the page that Server-Control was displayed outside of the form.
You can avoid this exception by overriding VerifyRenderingInServerForm
public override void VerifyRenderingInServerForm(Control control) { /* Confirms that an HtmlForm control is rendered for the specified ASP.NET server control at run time. */ } An alternative to overriding VerifyRenderingInServerForm is to remove the grid from the control collection during rendering, and then add it back when you are done before the page loads. This is useful if you want some kind of general helper method to get grid html, because you don't need to remember adding overrides.
Control parent = grid.Parent; int GridIndex = 0; if (parent != null) { GridIndex = parent.Controls.IndexOf(grid); parent.Controls.Remove(grid); } grid.RenderControl(hw); if (parent != null) { parent.Controls.AddAt(GridIndex, grid); } Another alternative to avoid overriding is the following:
grid.RenderBeginTag(hw); grid.HeaderRow.RenderControl(hw); foreach (GridViewRow row in grid.Rows) { row.RenderControl(hw); } grid.FooterRow.RenderControl(hw); grid.RenderEndTag(hw); Right after your Page_Load add this:
public override void VerifyRenderingInServerForm(Control control) { //base.VerifyRenderingInServerForm(control); } Please note that I am not doing anything in this function.
EDIT: Tim answered the same thing. :) You can also find the answer here
Here is my code
protected void btnExcel_Click(object sender, ImageClickEventArgs e) { if (gvDetail.Rows.Count > 0) { System.IO.StringWriter stringWrite1 = new System.IO.StringWriter(); System.Web.UI.HtmlTextWriter htmlWrite1 = new HtmlTextWriter(stringWrite1); gvDetail.RenderControl(htmlWrite1); gvDetail.AllowPaging = false; Search(); sh.ExportToExcel(gvDetail, "Report"); } } public override void VerifyRenderingInServerForm(Control control) { /* Confirms that an HtmlForm control is rendered for the specified ASP.NET server control at run time. */ } Just want to add another way to do this. I saw several people from different related questions ask if you can use VerifyRenderingInServerForm without adding it to the parent page.
You can actually do this, but it's a bit of a trap.
First create a new page class that looks something like this:
public partial class NoRenderPage : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } public override void VerifyRenderingInServerForm(Control control) { //Allows for printing } public override bool EnableEventValidation { get { return false; } set { /*Do nothing*/ } } } You do not need to have .ASPX associated with it.
Then, in the control you want to display, you can do something like the following.
StringWriter tw = new StringWriter(); HtmlTextWriter hw = new HtmlTextWriter(tw); var page = new NoRenderPage(); page.DesignerInitialize(); var form = new HtmlForm(); page.Controls.Add(form); form.Controls.Add(pnl); controlToRender.RenderControl(hw); You now have the original control displayed as HTML. If you need, add the control back to its original position. Now you have the HTML rendering, the page as usual and no changes on the page itself.