Cargar UserControl en un HTTPHandler y setear sus propiedades dinámicamente

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
image 

@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.
image

@ 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…

image

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.

Un comentario sobre “Cargar UserControl en un HTTPHandler y setear sus propiedades dinámicamente”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *