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


86
<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>

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 from com runat = "server", ainda estou recebendo este erro.

Alguma pista, por favor?


2
Já vi isso antes se alguém estiver usando uma página mestra que já tem uma tag de formulário (que pode ou não estar declarando runat="server"em sua <form>tag). Apenas um pensamento ...
lhan

@Lloyd: Mas não tenho nenhuma página mestra, criei esta página apenas para testar esse erro.
adolescente de

Olá, copiei seu código, mas não consigo replicar o problema. Você pode colocar todo o conteúdo do arquivo (cada linha) em sua pergunta, ou colar? Obrigado
christofr

Respostas:


174

Você está chamando GridView.RenderControl(htmlTextWriter), portanto, a página levanta uma exceção de que um Server-Control foi renderizado fora de um Form.

Você pode evitar essa execução substituindo VerifyRenderingInServerForm

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

Vejo aqui e aqui .


Eu tenho um GridView cujo conteúdo desejo processar em uma mensagem de email, é por isso que preciso renderizá-lo fora do formulário. Não posso substituir esse método porque a página do host é do Sharepoint. My Grid é um Usercontrol dentro de uma web part na página do sharepoint.
adolescente de

Além disso, quando adiciono esse GridView diretamente a um HtmlForm dinamicamente e, em seguida, renderizo, ele renderiza perfeitamente. Isso significa que requer apenas a presença de um formulário fora da grade. Mas, quando adiciono esse DIV ao HtmlForm dinamicamente, esse erro aparece novamente, embora o Grid seja filho do DIV e também adicionado ao HtmlForm junto com ele.
adolescente de

isso não funcionará se sua grade estiver dentro de um controle de usuário .ascx. nesse caso, veja a resposta de Chris Mullins abaixo. Usei as técnicas de Tim e Chris e elas funcionam muito bem.
Taylor Brown

Adoro uma solução elegante! Me deixa animado: D
Nikolay

3
Funcionou muito bem. Apenas para avisar, você pode obter um erro dizendo "RegisterForEventValidation só pode ser chamado durante Render ();" Se estiver definido, certifique-se de definir EventValidation como false na marcação da página.
Al Belmondo

29

Uma alternativa para substituir VerifyRenderingInServerForm é remover a grade da coleção de controles enquanto você faz a renderização e então adicioná-la de volta quando terminar, antes que a página carregue. Isso é útil se você deseja ter algum método auxiliar genérico para obter o html da 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 a substituição é 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);

Hábil!! Vou tentar amanhã.
adolescente de

ao tentar renderizar a grade dentro de um controle de usuário asp (.ascx), usar o primeiro método funcionou muito bem para mim.
Taylor Brown

3
1.Não funciona se o gridview contiver controles como LinkButton - dá 'Controle do tipo' LinkButton 'deve ser colocado dentro de uma tag de formulário com erro runat = server'. 2. Você poderia explicar por que essa técnica funciona?
BornToCode

@BornToCode Desabilite a classificação para seu gridview no código.
Adi Solar

14

Logo após o seu Page_Load, adicione este:

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

Observe que não faço nada na função.

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


2

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

Você realmente pode fazer isso, mas é um pouco complicado.

Primeiro, crie uma nova classe Page que se parece 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 necessário, adicione o controle de volta à sua posição original. Agora você tem o HTML renderizado, a página normalmente e nenhuma alteração na página em si.


@DanielEdwards, o que DesignerInitialize () faz por você?
JJS de

Isso funciona, mas eu precisava usar HttpContext.Current.Server.Execute(page, writer, false);para escrever o HTML - chamar controlToRender.RenderControl(hw);não levantou nenhum dos eventos de controle, por exemplo Page_Load, enquanto o controle estava sendo renderizado, ele estava vazio.
DGibbs de

0

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

Por que você adicionou esta resposta 5 anos depois de ser respondida? E é a mesma resposta.
Mukus
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.