GridView debe colocarse dentro de una etiqueta de formulario con runat = "servidor" incluso después de que GridView esté dentro de una etiqueta de formulario

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

Incluso GridView está dentro de una etiqueta from con runat = "server", todavía recibo este error.

¿Alguna pista por favor?

adolescente
fuente
2
He visto esto antes si alguien está usando una página maestra que ya tiene una etiqueta de formulario (que puede o no estar ya declarando runat="server"en su <form>etiqueta). Solo un pensamiento ...
lhan
@Lloyd: Pero no tengo ninguna página maestra, he creado esta página solo para probar este error.
teenup
Hola, copié su código pero no puedo replicar el problema. ¿Puede poner todo el contenido del archivo (cada línea) en su pregunta o pegarlo? Gracias
christofr
1
Se debe agregar un
Grant Thomas

Respuestas:

174

Está llamando GridView.RenderControl(htmlTextWriter), por lo tanto, la página genera una excepción de que un Control de servidor se procesó fuera de un formulario.

Puede evitar esta excepción anulando VerifyRenderingInServerForm

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

Vea aquí y aquí .

Tim Schmelter
fuente
Tengo un GridView cuyo contenido quiero convertir en un mensaje de correo electrónico, por eso necesito renderizarlo fuera de forma. No puedo anular este método porque la página de host es de Sharepoint. My Grid es un control de usuario dentro de un elemento web en la página de sharepoint.
teenup
Además, cuando agrego ese GridView directamente a un HtmlForm de forma dinámica y luego lo renderizo, se renderiza perfectamente. Esto significa que solo requiere la presencia de un formulario fuera de la cuadrícula. Pero, cuando agrego ese DIV al HtmlForm dinámicamente, este error vuelve a aparecer, aunque Grid es un elemento secundario de DIV y también se agrega a HtmlForm junto con él.
teenup
esto no funcionará si su cuadrícula está dentro de un control de usuario .ascx. en ese caso, vea la respuesta de Chris Mullins a continuación. He utilizado las técnicas de Tim y Chris y funcionan muy bien.
Taylor Brown
¡Amo una solución elegante! Me emociona: D
Nikolay
3
Funcionó muy bien. Solo un aviso, puede obtener un error que diga "RegisterForEventValidation solo se puede llamar durante Render ();" Si es así, asegúrese de establecer EventValidation en falso en el marcado de la página.
Al Belmondo
29

Una alternativa a la invalidación de VerifyRenderingInServerForm es eliminar la cuadrícula de la colección de controles mientras realiza el renderizado y luego volver a agregarla cuando haya terminado antes de que se cargue la página. Esto es útil si desea tener algún método auxiliar genérico para obtener grid html porque no tiene que acordarse de agregar la anulación.

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

Otra alternativa para evitar la anulación es hacer esto:

grid.RenderBeginTag(hw);
grid.HeaderRow.RenderControl(hw);
foreach (GridViewRow row in grid.Rows)
{
    row.RenderControl(hw);
}
grid.FooterRow.RenderControl(hw);
grid.RenderEndTag(hw);
Chris Mullins
fuente
¡¡Hábil!! Intentaré mañana.
teenup
al intentar representar la cuadrícula dentro de un control de usuario asp (.ascx), usar el primer método funcionó muy bien para mí.
Taylor Brown
3
1.No funciona si gridview contiene controles como LinkButton - da 'Control de tipo' LinkButton 'debe colocarse dentro de una etiqueta de formulario con el error runat = server'. 2. ¿Podría explicar por qué funciona esta técnica?
BornToCode
@BornToCode Deshabilita la ordenación de tu vista de cuadrícula en el código.
Adi Solar
14

Justo después de su Page_Load agregue esto:

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

Tenga en cuenta que no hago nada en la función.

EDITAR: Tim respondió lo mismo. :) También puedes encontrar la respuesta aquí

Ivan Nikolov
fuente
2

Solo quiero agregar otra forma de hacer esto. He visto a varias personas en varios hilos relacionados preguntar si puede usar VerifyRenderingInServerForm sin agregarlo a la página principal.

De hecho, puedes hacer esto, pero es un poco complicado.

Primero, cree una nueva clase Page que se parezca a lo siguiente:

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

No necesita tener un .ASPX asociado.

Luego, en el control que desea renderizar, puede hacer algo como lo siguiente.

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

Ahora tienes tu control original renderizado como HTML. Si es necesario, vuelva a colocar el control en su posición original. Ahora tiene el HTML renderizado, la página con normalidad y sin cambios en la página en sí.

Daniel Edwards
fuente
@DanielEdwards, ¿qué hace DesignerInitialize () por usted?
JJS
Esto funciona, pero necesitaba usarlo HttpContext.Current.Server.Execute(page, writer, false);para escribir el HTML: la llamada controlToRender.RenderControl(hw);no generó ninguno de los eventos de control, por ejemplo, Page_Loadasí que mientras el control se estaba procesando, estaba vacío.
DGibbs
0

Aquí está mi 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. */
    }
vipin
fuente
¿Por qué agregó esta respuesta 5 años después de que fue respondida? Y es la misma respuesta.
Mukus