c# .net user-controls render-html

RenderControl de UserControl está pidiendo una etiqueta de formulario en(C#.NET)



user-controls render-html (5)

Le pregunté cómo renderizar un HTML de UserControl y conseguí que el código funcionara para un UserControl generado dinámicamente.

Ahora estoy tratando de usar LoadControl para cargar un control generado previamente y escupir su HTML, pero me está dando esto:

El control del tipo ''TextBox'' debe colocarse dentro de una etiqueta de formulario con runat = server.

En realidad, no estoy agregando el control a la página, simplemente estoy tratando de tomar su HTML. ¿Algunas ideas?

Aquí hay un código con el que estoy jugando:

TextWriter myTextWriter = new StringWriter(); HtmlTextWriter myWriter = new HtmlTextWriter(myTextWriter); UserControl myControl = (UserControl)LoadControl("newUserControl.ascx"); myControl.RenderControl(myWriter); return myTextWriter.ToString();


Puede agregar un formulario a su control de usuario, o usar un cuadro de entrada html regular

<input type="text" />

Editar: si estás tratando de hacer algo AJAXy, tal vez quieras algo como esto http://aspadvice.com/blogs/ssmith/archive/2007/10/19/Render-User-Control-as-String-Template.aspx

public static string RenderView<D>(string path, D dataToBind) { Page pageHolder = new Page(); UserControl viewControl = (UserControl) pageHolder.LoadControl(path); if(viewControl is IRenderable<D>) { if (dataToBind != null) { ((IRenderable<D>) viewControl).PopulateData(dataToBind); } } pageHolder.Controls.Add(viewControl); StringWriter output = new StringWriter(); HttpContext.Current.Server.Execute(pageHolder, output, false); return output.ToString(); }

Puede eliminar la parte de enlace de datos si no es necesario.


Esta es una solución sucia que usé por el momento (ponerla en funcionamiento y luego hacerlo bien, ¿no?).

Ya había creado una nueva clase que hereda la clase UserControl y de la que derivaron todos los demás "UserControls" que creé. Lo llamé formPartial (guiño a Rails), y esto va dentro del método de cadena pública renderMyHTML ():

TextWriter myTextWriter = new StringWriter(); HtmlTextWriter myWriter = new HtmlTextWriter(myTextWriter); UserControl myDuplicate = new UserControl(); TextBox blankTextBox; foreach (Control tmpControl in this.Controls) { switch (tmpControl.GetType().ToString()) { case "System.Web.UI.LiteralControl": blankLiteral = new LiteralControl(); blankLiteral.Text = ((LiteralControl)tmpControl).Text; myDuplicate.Controls.Add(blankLiteral); break; case "System.Web.UI.WebControls.TextBox": blankTextBox = new TextBox(); blankTextBox.ID = ((TextBox)tmpControl).ID; blankTextBox.Text = ((TextBox)tmpControl).Text; myDuplicate.Controls.Add(blankTextBox); break; // ...other types of controls (ddls, checkboxes, etc.) } } myDuplicate.RenderControl(myWriter); return myTextWriter.ToString();

Desventajas de la parte superior de mi cabeza:

  1. Necesita una declaración de caso con todos los controles posibles (o controles que espera).
  2. Debe transferir todos los atributos importantes del control existente (cuadro de texto, etc.) al nuevo control en blanco.
  3. No aprovecha al máximo el método RenderControl de Controls.

Sería fácil confundir 1 o 2. Afortunadamente, sin embargo, esto ayuda a otra persona a encontrar una solución más elegante.


Alternativamente, podría deshabilitar ServerForm / Event-validation en la página que está procesando el control a una cadena.

El siguiente ejemplo ilustra cómo hacer esto.

public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { string rawHtml = RenderUserControlToString(); } private string RenderUserControlToString() { UserControl myControl = (UserControl)LoadControl("WebUserControl1.ascx"); using (TextWriter myTextWriter = new StringWriter()) using (HtmlTextWriter myWriter = new HtmlTextWriter(myTextWriter)) { myControl.RenderControl(myWriter); return myTextWriter.ToString(); } } public override void VerifyRenderingInServerForm(Control control) { /* Do nothing */ } public override bool EnableEventValidation { get { return false; } set { /* Do nothing */} } }


Puede agregar el control a la página, renderizar html y luego eliminar el control de la página.

O prueba esto:

Page tmpPage = new TempPage(); // temporary page Control tmpCtl = tmpPage.LoadControl( "~/UDynamicLogin.ascx" ); //the Form is null that''s throws an exception tmpPage.Form.Controls.Add( tmpCtl ); StringBuilder html = new StringBuilder(); using ( System.IO.StringWriter swr = new System.IO.StringWriter( html ) ) { using ( HtmlTextWriter writer = new HtmlTextWriter( swr ) ) { tmpPage.RenderControl( writer ); } }


Estaba teniendo el mismo problema al usar código similar a @TcKs y no he podido hacer que ninguno de estos ejemplos me funcione. Lo hice funcionar usando el método LoadControl de un UserControl como tal:

UserControl uc = new UserControl(); Control c = uc.LoadControl("newUserControl.ascx"); c.RenderControl(myWriter);