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:
- Necesita una declaración de caso con todos los controles posibles (o controles que espera).
- Debe transferir todos los atributos importantes del control existente (cuadro de texto, etc.) al nuevo control en blanco.
- 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);