Alejandro B. Martin - Blog de Asp.Net y MsSQL

Abril 25, 2008

Propiedades dinámicas

Con el presente explico -para aquellos a los que les pueda ser útil-, cómo consultar y asignar valores de forma dinámica a las propiedades de cualquier objeto o control de servidor. Requiere el Framework .Net 2.0+ (o superior)

A mi me costó bastante encotrar información, y me ha resultado de mucha utilidad para el gran proyecto -fase 1/3 para 2/3- que llevo desarrollando desde el 2007 [Fase1: GoldByWebs]

Primero mostraré el contexto con algún ejemplo y luego descubro el código mínimo-necesario para tal fin (para no enrollarse y para que descubras lo básico; así luego cada cual con lo suyo ..).

Supongamos que tenemos un GridView -o cualquier otro control e incluso un objeto(object)-, para el que los valores que queremos asignar a sus propiedades no los sabemos en tiempo de diseño; bien los recojemos de una base de datos, o bien de un array, o de donde sea pero sin saber de antemano; ni los valores que vamos a darlas, ni las mismas propiedades a las que asignar dichos valores, ..
-

EJEMPLO PRACTICO:
Tenemos un aplicativo en el que queremos que cada usuario pueda personalizar determinadas propiedades de un control GridView; al que llamaremos UserGridView.

Dynamic properties - Propiedades dinámicas con .Net

Los usuarios acceden a un formulario donde se les pide que definan que valores quieren personalizar para determinadas propiedades de un GridView:

El usuario Pepito a definido que quiere personalizar dicho gridview con los siguientes valores:
Caption = “Pepito quiere así su gridview”, Width = “400px” y Backcolor = “Yelow”

Fulanita por ello define:
Caption = “GridView de Fulanita”, Width = “550px” , Backcolor = “Pink” y BorderStyle=”Dashed”.

Dichos datos son guardados -están almacenados pues- en la base de datos.


COMO PODEMOS HACER PARA QUE A LOS USUARIOS SE LES MUESTRE EL GRID COMO ELLOS QUERIAN. COMO PODEMOS ASIGNAR PROPIEDADES DE FORMA DINAMICA EN .NET

::TENIENDO Y TOMANDO COMO BASE::

-Que determinada consulta a la base de datos para determinado usuario a devuelto un List(of ListItem) con el par “NombreDePropiedad/ValorQueDefinióElUsuario” (.text/.value) [aunque también podría tratarse de un datatable, etc ..]

Lo que muchos hacen, -sólo si saben las propiedades que pueden definir los usuarios, o bien si implementan condicionales tipo If Not IsNothing- es programar algo así como:
-EJEMPLO NO DINÁMICO-

‘[Consulta a la DBA para rellenar este List con el Par NombrePropiedad/Valor (.text/.value)]
Dim ObjPropertiesListOfListItem As New List(Of ListItem)


‘ Según el gráfico, en este caso No Dinámico, sabemos que 0=Caption

UserGridView.Caption = ObjPropertiesListOfListItem(0).Value

UserGridView.Width = ObjPropertiesListOfListItem(1).Value

‘ ..

-
-EJEMPLO DINAMICO- IMPLEMENTANDO PROPIEDADES DINAMICAS EN .NET - REFLECTION

        '.. [Consulta a la DBA para rellenar este List con el Par NombrePropiedad/Valor (.text/.value)]
        Dim ObjPropertiesListOfListItem As New List(Of ListItem)
yyy
        'Creamos un ArrayList que se rellena con las propiedades que descubre la Function arrPropiedadesDeObjeto para el GridView
        Dim arrDePropiedadesDeMiUserGridView As ArrayList = arrPropiedadesDeObjeto(UserGridView)
        'Para tantas propiedades customizadas cómo se recojiesen de la dba (almacenadas en: ObjPropertiesListOfListItem)
        For x = 0 To ObjPropertiesListOfListItem.Count - 1
            'Comprobamos si el objeto (UserGridView) admite -tiene- x determinada propiedad; buscando si esta en el array
            If arrDePropiedadesDeMiUserGridView.Contains(ObjPropertiesListOfListItem(x).Text) Then
                'Si fuere el caso, llamamos a SetProperty para customizar el objeto con el valor de propiedad
                SetProperty(UserGridView, ObjPropertiesListOfListItem(x).Text, ObjPropertiesListOfListItem(x).Value)
            End If
        Next

Ahora el Function y el Sub, tan esperados !!

    ''' <summary>Devuelve un array que contiene las propiedades de determinado objeto.</summary>
    ''' <param name="objeto">Cualquier objeto; aunque normalmente suelen ser Controles de Servidor</param>
    Public Function arrPropiedadesDeObjeto(ByVal objeto As Object) As ArrayList
        Dim PropertyInfo As System.Reflection.PropertyInfo() = objeto.GetType.GetProperties() 'Me.GetType.GetProperties()
        Dim PropertyItem As System.Reflection.PropertyInfo
        Dim _arrAvolver As New ArrayList
        For Each PropertyItem In PropertyInfo : _arrAvolver.Add(PropertyItem.Name) : Next
        Return _arrAvolver
    End Function
    ''' <summary>Adjudica un valor a una propiedad de un determinado objeto</summary>
    ''' <param name="Objeto">El objeto al que -por reflection- pasar el PropertyValue</param>
    ''' <param name="PropertyName">El nombre de la propiedad</param>
    ''' <param name="PropertyValue">El valor que se la quiere adjudicar</param>
    Public Sub SetProperty(ByVal Objeto As Object, ByVal PropertyName As String, ByVal PropertyValue As String)
        Dim userType As Type = Me.GetType()
        Dim UserProp As System.Reflection.PropertyInfo = userType.GetProperty(PropertyName)
        UserProp.SetValue(Objeto, PropertyValue, Nothing)
    End Sub

Las ventajas que ofrece el uso del dinamismo, són enormes en lo que refiere a escalabilidad, aunque hay que anotar que el uso de “Reflection” siempre conlleva una demora de tiempo, es decir, que las páginas o forms tardarán algo más en cargarse, pero no mucho ..

Copyright 25 Abril 2008 © Alejandro Barrada Martin - Reservados todos los derechos salvo consentimiento del autor.
El autor cede los derechos de publicación del presente artículo siempre y cuando se mencione al mismo y a esta url-dirección web.

Diciembre 25, 2007

HtmlMeta - Cómo programar dinámicamente las etiquetas Meta del head

Con esta entrada, voy a explicar cómo programar dinámicamente las etiquetas meta de la cabecera de las páginas web que se quieran programar con código Asp.Net.

Dichas etiquetas son fundamentales entre otras cosas, para conseguir un buen posicionamiento en buscadores web.
En este post no voy a explicar su importancia, aquí voy a explicar cómo manipularlas bajo código asp.net (vb codebehind), ideal para todo aquel que (como yo) quiera generar url’s dinámicas (labor importante para SEOs) para alguno de sus proyectos, aunque también e importante en cualquier caso si quieres especificar sus valores desde una base de datos.
Nota: Para escribir el título de la página (title) , no hace falta recurrir a dicho objeto, pues para tal fin bastará con usar:

Page.Title = “El título de la página” ‘<– como vemos, especificar el título es bastante sencillo

El objeto que lleva a cabo todas las labores de programación lado servidor de las etiquetas Meta es el:

HtmlMeta

Para todas las etiquetas meta (description, keywords, copyright, content-language, etc ..), habrá que utilizar el citado objeto. Ante todo debo incidir que en la etiqueta <Head> de nuestro .aspx, deberemos poner (si no esta), el argumento RunAt=”Server”
Veamos en un ejemplo cómo podemos escribir de forma programática bajo asp.net la etiqueta description:

EJEMPLO 1: Escribir el título de la página y la etiqueta Description

Page.Title = “El título de la página” ‘<– como vemos, especificar el título es bastante sencillo

Dim HeaderMetaTags As New HtmlMeta ‘Instanciamos el objeto

HeaderMetaTags.Name = “Description” ‘Le atribuimos el nombre de la etiqueta que tendrá que escribir en la pág.

HeaderMetaTags.Content = “La descripción de su página web” ‘Le indicamos su valor

‘Le indicamos a la cabecera de la página (page.header), que añada dicho objeto que se encargará de escribirla

Page.Header.Controls.Add(HeaderMetaTags)

Titulo y etiqueta Description

Ahora te dirás, ¡ bien pues ya puedo empezar a escribir todas las etiquetas que considere !,
pero advertencia !, al crear (querer poner) varias etiquetas, tendrás que crear una instancia nueva del objeto HtmlMeta (y con diferente nombre) para cada etiqueta que quieras poner.

EJEMPLO 2: para escribir 2 o más etiquetas (description, keywords)

Verás pues que si utilizas el siguiente:
CODIGO INCORRECTO

Dim HeaderMetaTags As New HtmlMeta ‘Instanciamos el objeto

HeaderMetaTags.Name = “Description” ‘Le atribuimos el nombre de la etiqueta que tandrá que escribir en la pág.

HeaderMetaTags.Content = “La descripción de su página web” ‘Le indicamos su valor

‘Le indicamos a la cabecera de la página (page.header), que añada dicho objeto que se encargará de escribirla

Page.Header.Controls.Add(HeaderMetaTags)

‘|||Si utilizamos la misma instancia del HtmlMeta, .net sólo escribirá la última||| ———- PARTE DE CODIGO ERRONEO ———-

HeaderMetaTags.Name = “Keywords”

HeaderMetaTags.Content = “palabra_clave1, palabras clave2, etc ..”

Page.Header.Controls.Add(HeaderMetaTags)


RESULTADO INCORRECTO

Captura de pantalla - HtmlMeta Description y Keywords de forma incorrecta

Fíjate que en el código fuente de la pag., ¡ sólo se esta escribiendo la última etiqueta programada !, y no las 2 (description y keywords)
Como comenté, tendrás que crear una instancia nueva para cada etiqueta

CODIGO CORRECTO AUNQUE MEJORABLE (luego explico como mejorarlo)

Dim HeaderMetaTags_Descripcion As New HtmlMeta ‘Instanciamos el objeto para la etiqueta Description

HeaderMetaTags_Descripcion.Name = “Description” ‘Le atribuimos el nombre de la etiqueta

HeaderMetaTags_Descripcion.Content = “La descripción de su página web” ‘Le indicamos su valor

Page.Header.Controls.Add(HeaderMetaTags_Descripcion)

Dim HeaderMetaTags_PalabrasClave As New HtmlMeta ‘Instanciamos una 2ª nueva instancia del objeto

HeaderMetaTags_PalabrasClave.Name = “Keywords”

HeaderMetaTags_PalabrasClave.Content = “palabra_clave1, palabras clave2, etc ..”

Page.Header.Controls.Add(HeaderMetaTags_PalabrasClave)

RESULTADO CORRECTO AUNQUE MEJORABLE

Captura de pantalla - HtmlMeta Description y Keywords de forma correcta pero bastante mejorable

Como ves, utilizando el código anterior conseguimos que figuren las 2 etiquetas. ¿ Pero porque mejorable ?
Te dirás .. Que palo, o .. que mal eso de tener que escribir una instancia nueva para cada etiqueta, además ..
¿ Y si se quieren escribir tantas etiquetas como así estuvieran en una base de datos ?
Para tal fin, fuera el que fuese, si no queremos tener que escribir una nueva instancia para cada etiqueta (y así escribir menos líneas de código), hay que emplear arrays y un bucle que recorra sus items para escribir las etiquetas.

EJEMPLO 3: Escribimos 3 etiquetas meta (o tantas como se precise)

CODIGO CORRECTO CASI PERFECTO

Dim HeaderMetaTagsArray_Nombres As New ListItemCollection ‘Nuevo array para los nombres de etiquetas (tantos como de ellas queramos poner)

HeaderMetaTagsArray_Nombres.Add(“Description”)

HeaderMetaTagsArray_Nombres.Add(“Keywords”)

HeaderMetaTagsArray_Nombres.Add(“Copyright”)

Dim HeaderMetaTagsArray_Valores As New ListItemCollection ‘Nuevo array para los valores (el content de la etiqueta) (tantos como el anterior array)

HeaderMetaTagsArray_Valores.Add(“Mi descripcion es ..”)

HeaderMetaTagsArray_Valores.Add(“Palabra1, palabra2, ..”)

HeaderMetaTagsArray_Valores.Add(“Alejandro B. Martin”)

For i = 0 To HeaderMetaTagsArray_Nombres.Count - 1 ‘Recorremos un bucle desde 0 hasta el total de etiquetas que queramos poner (definidas en 1er array)

Dim HeaderMetaTags As New HtmlMeta ‘al estar dentro de un bucle, se irá creando (instanciando nuevamente) dicho objeto cada vez que pertoque

HeaderMetaTags.Name = HeaderMetaTagsArray_Nombres(i).Value

HeaderMetaTags.Content = HeaderMetaTagsArray_Valores(i).Value

Page.Header.Controls.Add(HeaderMetaTags) ‘Así pues para cada etiqueta (en HeaderMetaTagsArray_Nombres) se escribirá correctamente.

Next

RESULTADO CASI PERFECTO

Captura de pantalla - HtmlMeta Varias etiquetas de forma casi perfecta

Y ahora me preguntarás ¿Porque casi perfecto ?
Realmente ya esta bien, pero el código debería mejorarse en cualquiera de los siguientes casos:

  • Quieres aprender más | y/o
  • Te gusta hacer tus proyectos lo mejor posible | y/o/u opcional
  • Estas buscando posicionar bien tus páginas en los navegadores (SEO)

Llegado a este punto, ya lo tienes casi todo, pero si buscas la perfección y el buen hacer, verás que el resultado (acude al navegador y haz ver código fuente de l página) no queda todo lo deseable que esperaríamos de cualquier página web escrita manualmente, y el objetivo es hacer parecer a la página lo más similar a como si se hubiesen puesto las etiquetas manualmente (util para SEOs como yo, jj).

Fíjate en la captura de pantalla anterior y verás que:
Las etiquetas aparecen seguidas todas ellas, sin dejar la línea de retorno de carro típica, y ello quizá no sea lo más correcto si nuestro fin es el posicionamiento (y no queremos que google se de cuenta de que es una página dinámica, pues no le gustan tanto como las estáticas, pues el prefiere .htm (si es que ..)), vamos que lo correcto sería encontrarse en la página algo así como:

<head>
<title>Titulo</title>
<meta name=”x” content=”x”>
<meta name=”y” content=”y”>
..
</head>

Pues ahora explico el “resultado perfecto” (recordemos que nadie es perfecto pero ello no quita de)

CODIGOPERFECTO

Además de lo comentado (situar espaciadamente las etiquetas), si nuestro objetivo es el conseguir el buen posicionamiento en cuantos más buscadores mejor, además definiremos ampliamente a cada una de las etiquetas meta, pues además de la tan conocida propiedad Name, también existen para casi el mismo fin HttpEquiv e ID (y nosotros queremos que todos los buscadores nos entiendan y de paso vean que bien trabajamos, jj).

Para poder dar el retorno de carro después de que se escriba cada etiqueta utilizaremos el objeto literal para escribir dicho retorno de carro jto. a un espaciado tab.

Page.Title = “El título de la página” ‘<– como vemos, especificar el título es bastante sencillo

Dim HeaderMetaTagsArray_Nombres As New ListItemCollection ‘Nuevo array para los nombres de etiquetas (tantos como de ellas queramos poner (3 en este ejemplo))

HeaderMetaTagsArray_Nombres.Add(“Description”)

HeaderMetaTagsArray_Nombres.Add(“Keywords”)

HeaderMetaTagsArray_Nombres.Add(“Copyright”)

Dim HeaderMetaTagsArray_Valores As New ListItemCollection ‘Nuevo array para los valores (el content de la etiqueta) (tantos como el anterior array)

HeaderMetaTagsArray_Valores.Add(“Mi descripcion es ..”)

HeaderMetaTagsArray_Valores.Add(“Palabra1, palabra2, ..”)

HeaderMetaTagsArray_Valores.Add(“Alejandro B. Martin”)

For i = 0 To HeaderMetaTagsArray_Nombres.Count - 1 ‘Recorremos un bucle desde 0 hasta el total de etiquetas que queramos poner (definidas en 1er array)

Dim HeaderMetaTags As New HtmlMeta ‘al estar dentro de un bucle, se irá creando (instanciando nuevamente) dicho objeto cada vez que pertoque

HeaderMetaTags.Name = HeaderMetaTagsArray_Nombres(i).Value

HeaderMetaTags.HttpEquiv = HeaderMetaTagsArray_Nombres(i).Value

HeaderMetaTags.ID = HeaderMetaTagsArray_Nombres(i).Value

HeaderMetaTags.Content = HeaderMetaTagsArray_Valores(i).Value

Dim SaltoDeLinea As Literal = New Literal() ‘Utilizamos el objeto literal

SaltoDeLinea.Text = vbCrLf & vbTab ‘(salto de linea) (espaciado TAB)

Page.Header.Controls.Add(SaltoDeLinea)

Page.Header.Controls.Add(HeaderMetaTags) ‘Así pues para cada etiqueta (en HeaderMetaTagsArray_Nombres) se escribirá correctamente.

If i = HeaderMetaTagsArray_Nombres.Count - 1 Then Page.Header.Controls.Add(New LiteralControl(vbCrLf)) ‘llego al final y también queremos retorno de carro (esta vez sin el TAB)

Next

RESULTADOPERFECTO

Captura de pantalla - Varias etiquetas(tag) Meta de la mejor forma (o casi !, je je)

Aunque ..
Como decía en una linea aquello de que nadie es perfecto, y si miras bien el resultado, verás que para rematar la faena, aún queda dejar un retorno de carro y espaciados para la etiqueta title, y ella no se manipula con el objeto HtmlMeta sino directamente a través de page.title, pues como hacerlo, como hacer que quede del todo perfecto ..

.. eso es cosa tuya !

Copyright 26 Diciembre 2007 © Alejandro B. Martin - Reservados todos los derechos salvo consentimiento del autor.
El autor cede los derechos de publicación del presente artículo siempre y cuando se mencione al mismo y a esta url-dirección web.

Blog de WordPress.com.