O GridView deve ser colocado dentro de uma tag de formulário com runat = “server” mesmo depois que o GridView estiver dentro de uma tag de formulário

 
grid view:

Código por trás:

 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(); } } 

Mesmo o GridView está dentro de uma tag com runat = “server”, ainda estou recebendo este erro.

Alguma pista, por favor?

Você está chamando GridView.RenderControl(htmlTextWriter) , portanto, a página gera uma exceção que um controle de servidor foi processado fora de um formulário.

Você pode evitar essa execução sobrescrevendo o VerifyRenderingInServerForm

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

Veja aqui e aqui .

Uma alternativa para replace VerifyRenderingInServerForm é remover a grade da coleção de controles enquanto você faz a renderização e, em seguida, incluí-la novamente quando terminar, antes de carregar a página. Isso é útil se você quiser ter algum método auxiliar genérico para obter html de grade, porque você não precisa se lembrar de adicionar a substituição.

 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); } 

Outra alternativa para evitar o override é fazer isso:

 grid.RenderBeginTag(hw); grid.HeaderRow.RenderControl(hw); foreach (GridViewRow row in grid.Rows) { row.RenderControl(hw); } grid.FooterRow.RenderControl(hw); grid.RenderEndTag(hw); 

Logo após o seu Page_Load, adicione isto:

 public override void VerifyRenderingInServerForm(Control control) { //base.VerifyRenderingInServerForm(control); } 

Note que eu não faço nada na function.

EDIT: Tim respondeu a mesma coisa. 🙂 Você também pode encontrar a resposta aqui

Só quero adicionar outra maneira de fazer isso. Eu vi várias pessoas em vários tópicos relacionados perguntar se você pode usar VerifyRenderingInServerForm sem adicioná-lo à página pai.

Você realmente pode fazer isso, mas é um bocado.

Primeiro, crie uma nova class de página que se pareça com o seguinte:

 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*/ } } } 

Não precisa ter um .ASPX associado a ele.

Então, no controle que você deseja renderizar, você pode fazer algo como o seguinte.

  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); 

Agora você tem seu controle original renderizado como HTML. Se você precisar, adicione o controle de volta à sua posição original. Agora você tem o HTML renderizado, a página como normal e sem alterações na própria página.

Aqui está o meu código

 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. */ }