Necesite reutilizar un UserControl dentro de un controlador HTTP, pero me di cuenta que no puede realizar una referencia a mi UserControl como lo hacemos en las paginas .aspx, es decir no tenia forma de definir el tipo de control como para luego acceder a sus propiedades.
Veamos algo como veníamos utilizando al UserControl….
Cuando en una pagina .aspx normal (por llamarla de alguna manera) necesitamos utilizar un UserControl, lo arrastramos hacia ella y listo.
Se nos registra con la directiva @Register el UC para poder utilizarlo, junto con el Tagname y el TagPrefix
@Register:
Crea una asociación entre un prefijo de etiqueta y un control personalizado, lo que proporciona a los desarrolladores una forma concisa de hacer referencia a controles personalizados en un archivo de aplicación ASP.NET (incluidos páginas Web, controles de usuario y páginas principales).
Cuando necesitamos utlizarlo en algun propiedad o llamarlo desde el codigo debemos, podemos hacer uso de la directiva @Reference, para que se compile y agregue la referencia (es como registrar las antiguas DLL’s…)
Asi podremos utilizar la referencia al objeto externo compilado y a sus miembros públicos desde el archivo actual.
@ Reference:
Indica que otro control de usuario, archivo de código fuente de página o archivo arbitrario que se encuentra en alguna ruta de acceso virtual debe compilarse dinámicamente y vincularse al archivo ASP.NET actual (página Web, control de usuario o página principal) en el que se declara esta directiva.
Y en el HTTPHandler (.ashx) ??
Aquí no tenemos estas directivas u opciones…
La forma que encontré es mediante Reflection, obteniendo el tipo
Dim miCtrl As UserControl = pagina.LoadControl("~/modulos/ucEjemplo.ascx") Dim tipoControl As Type = miCtrl.GetType
Y luego mediante esta formidable clase.. puedo Obtener una propiedad y setearla
Dim propiedadExpedienteId As System.Reflection.PropertyInfo = tipoControl.GetProperty("ExpedienteId") Dim valor As Int32 = 4442 propiedadExpedienteId.SetValue(miCtrl, valor, Nothing)
Luego ejecuto la pagina que tengo como ayuda (que me permitió cargar el control con LoadControl) y lo guardo en un StringWriter
Dim wr As System.IO.StringWriter = New System.IO.StringWriter() HttpContext.Current.Server.Execute(pagina, wr, False)
Aquí esta el código completo del ejemplo:
Public Class Ejemplo : Implements IHttpHandler Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest context.Response.Clear() context.Response.ContentType = "text/html" context.Response.Write(ObtenerContenido) context.Response.End() End Sub Private Function ObtenerContenido() As String Dim pagina As Page = New Page() Dim miCtrl As UserControl = pagina.LoadControl("~/modulos/ucEjemplo.ascx") Dim tipoControl As Type = miCtrl.GetType 'Ejemplo: valor 4442 tipoControl.GetProperty("ExpedienteId").SetValue(miCtrl, 4442, Nothing) pagina.Controls.Add(miCtrl) Dim wr As System.IO.StringWriter = New System.IO.StringWriter() HttpContext.Current.Server.Execute(pagina, wr, False) Dim cadenaSalida As String = wr.ToString() wr.Close() Return cadenaSalida End Function Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable Get Return False End Get End Property End Class
Enviar el contenido de un UserControl por WebService
Idem a lo anterior:
<WebMethod()> _ <System.Web.Script.Services.ScriptMethod()> _ Public Function Actuaciones(ByVal contextKey As String) As String Dim pagina As Page = New Page() Dim miCtrl As UserControl = pagina.LoadControl("~/modulos/Ejemplo.ascx") Dim tipoControl As Type = miCtrl.GetType Dim propiedadExpedienteId As System.Reflection.PropertyInfo = tipoControl.GetProperty("ExpedienteId") Dim valor As Int32 = Convert.ToInt32(contextKey) propiedadExpedienteId.SetValue(miCtrl, valor, Nothing) pagina.Controls.Add(miCtrl) Dim wr As System.IO.StringWriter = New System.IO.StringWriter() HttpContext.Current.Server.Execute(pagina, wr, False) Dim cadenaSalida As String = wr.ToString() wr.Close() Return cadenaSalida End Function
Este webmethod es especial por el parámetro que recibe, ya que lo utilizo dentro de un TabPanel para obtener los datos dinámicamente…
En este ejemplo seteo la propiedad DynamicContextKey con un valor para test, la idea es que luego se establezca por código cuando se carga la pagina.
<cc2:TabPanel ID="TabPases" runat="server" HeaderText="Historial de Pases" DynamicContextKey="4442" DynamicServiceMethod="Pases" DynamicServicePath="/servicios/expedientesWS.asmx"> <ContentTemplate> </ContentTemplate>
Enlaces
- @ Register
Crea una asociación entre un prefijo de etiqueta y un control personalizado, lo que proporciona a los desarrolladores una forma concisa de hacer referencia a controles personalizados en un archivo de aplicación ASP.NET (incluidos páginas Web, controles de usuario y páginas principales). - @ Reference
Indica que otro control de usuario, archivo de código fuente de página o archivo arbitrario que se encuentra en alguna ruta de acceso virtual debe compilarse dinámicamente y vincularse al archivo ASP.NET actual (página Web, control de usuario o página principal) en el que se declara esta directiva. - Introducción a los controladores HTTP
- IHttpHandler (Interfaz)
Define el contrato que ASP.NET implementa para procesar de forma sincrónica las solicitudes Web HTTP mediante controladores HTTP personalizados. - Object.GetType (Método)
Obtiene el objeto Type de la instancia actual. - Type (Clase)
Representa declaraciones de tipo: tipos de clase, tipos de interfaz, tipos de matriz, tipos de valor, tipos de enumeración, parámetros de tipo, definiciones de tipo genérico y tipos genéricos construidos abiertos o cerrados. - Type.GetProperty (Método)
Obtiene una propiedad específica del objeto Type actual. - PropertyInfo (Clase)
Descubre los atributos de una propiedad y proporciona acceso a los metadatos de la misma. - PropertyInfo.SetValue (Método)
Establece el valor de propiedad del objeto especificado en el valor indicado.
Muy bueno, me resulto util y práctico.