martes, 22 de enero de 2008

Confirmación de borrado en un Grid más avanzado.

Hace casi un mes escribí la siguiente entrada que trataba de un método limpio y sencillo de visualizar una ventana de confirmación en javascript desde cualquier control .net que aceptara el oncClientClick.

Hoy traigo la versión más avanzada para realizarlo en un GridView en donde tengamos en una columna un texto descriptivo y en otra un enlace para borrar la fila.
La teoría es añadir al enlace de borrado el parámetro OnClientClick invocando el Javascript que nos saca la alerta y que es:

function fnConfirmacionBorrado(value)
{
return window.confirm('El registro ' + value + ' va ha ser eliminado, ¿Desea continuar?');
}


Despues hacemos el método que borra al entrada físicamente de la fuente de datos y que aquí no voy a describir por ser cansinamente repetitivo. Al que llamaremos borra().

Por último en el momento en que .NET va a ir rellenando fila a fila el GridView, incluiremos el OnClientClick introduciendo el valor de la columna con la descripción como el mensaje ‘value’ que le enviaremos a la función javascript.

Protected Sub gvListado_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvListado.RowDataBound

‘ Recuperamos el enlace de eliminar.
Dim eliminar As LinkButton = CType(e.Row.FindControl("lnkEliminar"), LinkButton)

‘ Recuperamos la etiqueta con la descripción
Dim descripcion As Label = CType(e.Row.FindControl("lblDescripcion"), Label)

‘ comprobamos que no sea nothing para que no falle.
If Not IsNothing(eliminar) Then
eliminar.OnClientClick = "return fnConfirmacionBorrado('" & descripcion.Text & "');"
End If

End Sub


Es importante tener en cuenta el detalle que el javascript nos tiene que devolver un valor true o false para invocar o no la funcion borra(), para ello debemos de ponerle el return antes del nombre de la función javascript que nos muestra la ventana de confirmación.

Por último el GridView estaría construido de la siguiente forma:

<'asp:gridview id="gvListado" runat="server">
<'columns>
<'asp:templatefield>
<'headertemplate>Descripción <'/headertemplate>
<'itemtemplate>
<'asp:label id="lblDescripcion" runat="server" text="<%# eval("") %>" />
<'/itemtemplate>
<'/asp:templatefield>
<'asp:templatefield>
<'itemtemplate>
<'asp:linkbutton id=" lnkEliminar " onclick="Borrar" runat="server" text="Eliminar" causesvalidation="false">
<'/itemtemplate>
<'/asp:templatefield>
<'/columns>
<'/asp:gridview>

domingo, 6 de enero de 2008

Felizes reyes magos!!

... y más porque mañana es fiesta!! :D

Añadir item a un combo o utiliza el Intellisense más.

A veces la lógica de la programación con .NET me sorprende. Tiene sentido pero me sorprende.

El que aquí escribe lleva programando suficientes años para haber pasado por varias metodologías empezando por la PPE (Programación Plato de Espaguetis) basada en Goto y Gosub, la dureza del ensamblador con GEM, pasando por los predicados del PROLOG, el lenguaje estructurado del Turbo Pascal, la programación basada en eventos del LINGO, la exasperante simpleza del HTML (que NO es un lenguaje de programación), el tostón retorcido del Java Script y el ActionScript, o el indescriptible XSLT (que ES un lenguaje de programación).

Si ya con el ASP clásico siempre tuve la sensación que me perdía gran parte de la potencia de las capacidades, con .NET tengo la certeza (y más ahora con la certificación) que es un enorme mundo con una lógica muy especial en relación a mis anteriores experiencias.

Todo esto viene a cuento de que estoy haciendo una pequeña aplicación para practicar parte del material que tengo que preparar para el examen de Febrero, y estoy centrado en un menú desplegable.

En la anterior entrada daba un ejemplo del cómo definir qué columnas de un origen de datos para el valor y el texto de un ítem del dropDownList. Obviamente el paso siguiente era incluir una nueva option al principio del combo que tenga como valor el “0” y el texto “Haga una selección”.

Y allí voy yo tan contento diciéndome a mí mismo –esto está chupao, si los ítem son una colección pues le añado un ítem en la posición 0 y san se ha acabao-

dropDownList.DataSource = dataTable
dropDownList.DataValueField = "campo1"
dropDownList.DataTextField = "campo2"
dropDownList.DataBind()

dropDownList.Items.Insert(0,”Haga una selección”)

… pues no. De esta manera efectivamente inserto en la posición 0 la option con el texto elegido, pero también me introduce la cadena como valor. Dita sea, no encuentro la forma de poder introducir un ítem con tres parámetros. Es decir, la posición para insertarlo, el valor y el texto.

Ale, a tirar de San Google, y así me encuentro en algún ejemplo la lógica aplastante a la que me tengo que ir acostumbrando y que no es otra que en .NET TODO es un objeto.

Si invoco el Intellisense me informa que el método Insert tiene dos sobrecargas. Una en donde el ítem es una cadena de texto, como lo hago arriba, y una segunda en donde me admite un entrada tipo ListItem.

La declaración del New de un ListItem tiene varias sobrecargas pero me interesa la tercera que me permite introducir el campo texto y el campo valor.

Y así, y para terminar este largo post, está es una forma elegante de introducir el ítem al principio del combo con los datos del texto y el valor que quiero.

dropDownList.Items.Insert(0, New ListItem("Sin restricción por tipo de matricula", 0))

viernes, 4 de enero de 2008

dataValueField y dataTextField, la potencia de la sencillez.

Bueno, esto es una mini entrada sobre una pequeña capacidad que tienen los controles tipo dropDownList, entre nosotros menús desplegables, que se trata de poderle decir qué campos del origen de datos vamos a utilizar para rellenarlo (Bind).

Veamos el ejemplo y luego lo analizamos:

dropDownList.DataSource = dataTable
dropDownList.DataValueField = "campo1"
dropDownList.DataTextField = "campo2"
dropDownList.DataBind()

Primero tenemos definido un control tipo combo llamado dropDownList y seleccionamos la tabla dataTable como la fuente de datos.

El truco del almendruco viene a continuación, ya que puedo indicarle por medio del nombre del campo de la tabla, cual quiero que sea el que se use para el value y cual para el texto visible.

¿Qué tiene esto de interesante? Pues así a bote pronto puedo traerme una tabla con 50 campos y utilizarla para rellenar diferentes combos al poder definir que columnas usar para cada uno. Lo cual también me lleva a que si lo introduzco en un SELECT CASE, puedo poblar el combo de manera condicional o, incluso de manera aún más interactiva, que se rellenen los menús de acuerdo a eventos de usuario. O, liandola más, que pueda seleccionar más de un value en cada combo (sincronizando la selección con la tabla).

Una capacidad sencillita pero que descarga mucho las llamadas a la base de datos y mejora la dura vida del programador.

P.D. No debería, pero recordaré que un dropDownList no es más que un control .NET que genera el código html tal cual el siguiente:

<.select>
<.option value="value">text
<./select>


En donde se observa en donde se representan cada uno de los dos valores antes mencionados.

jueves, 3 de enero de 2008

Expresiones Regulares, esas grandes desaprovechadas.

He de reconocer que esta certificación cada día me abre las puertas a formas de desarrollar más simples y eficiente. Y también he de reconocer que los programadores tenemos tendencia a si no entendemos el concepto en los primeros quince minutos, olvidarnos del tema y seguir con la cuenta de la abuela.

Esto viene al caso porque hoy estoy liado con un proyecto personal y estoy haciendo la validación de los campos de una clase dentro de un método privado. Y me he acordado del lio de condicionales que tienes que montar para validar un email, y más aún ahora con los subdominios tipo .com.ar o .eu.nom.

Y he vuelto a recuperar una vieja investigación que dejé en su momento y que me ha vuelto aparecer en la certificación. Expresiones regulares.

No voy a hacer un discurso de qué son y porqué son tan raras. Pero si hay que dejar clarísimo que es el método más eficiente, compacto y elegante para extraer información de cadenas alfanuméricas para, por ejemplo, validar que cumple los requisitos necesarios.

En .NET 2.0 está chupado:

Primero importamos la clase System.Text.RegularExpressions, despues creamos una variable del tipo Regex. A continuación la instanciamos con la cadena que contiene la expresión regular… y ya ta!!

Mirad que sencillo:

Private Function compruebaEmail() As Boolean
Dim ok As Boolean = False
Dim r As Regex

r = New Regex("^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$")
ok = r.IsMatch(email)

Return ok

End Function

Lo más lioso, con mucho, es la construcción de la expresión regular en sí, pero para ello existen librerías muy completas en Internet.

A continuación os pongo unos enlaces recomendados:

1. El sitio del “boss” de Visual Basic.Net en España… El Guille:

2. La mejor y más completa librería de expresiones regulares que he encontrado:
3. Wikipedia en Español:
Eha, a disfrutarlo.

miércoles, 2 de enero de 2008

Feliz Año 2008!!!

Oño, me se había olvidado...

Cadenas seguras y POO.

Como en todos los proyectos, en este (la certificación) también me ha pillado el toro y estoy estudiando a marchas forzadas para presentarme al examen en febrero. Por ello he tardado tanto en hacer otra entrada.

Ahora mismo estoy machacando todo el tema de seguridad y me ha llamado la atención la poca o nula información e implementación de buenas maneras con respecto a la seguridad de la información que observo tanto en mi pasado laboral como en las decenas de compañeros con quienes he trabajado.

Ninguno teníamos en cuenta que con traceando la memoria (algo simple y sencillo) se puede acceder a esa información a la que NADIE debería acceder, menos su destinatario.

Por ello un pequeño capítulo al final del temario de seguridad me ha llamado poderosamente la atención y también me ha servido para hacer un poquito de programación orientada a objetos que, vergüenza la mía, tiene poquito que ver con la programación que he realizado antes de este curso.

OBJETIVO: Quiero coger una cadena de texto, y poderla codificar y recuperar de forma sencilla. De forma que nadie la pueda leer en la memoria. Y que cuando la use, desaparezca todo rastro de su contenido.

Pues bien, en antiguos y cercanos tiempos, hubiera escrito dos o tres mil líneas para obtener lo que obtengo con la clase que he escrito a continuación y que me parece de lo más elegante.

Private Class cadenaSegura
‘Declaro dos campos de la clase.
Dim cadena As String = String.Empty
Dim clave As SecureString

‘ En la declaración New instancio una nueva clase SecureString
‘ que me hace almacena el string en memoria pero codificandolo
‘ con DPAPI. Le asigno el texto a el campo cadena y que me
‘ lo codifique.
Public Sub New(ByVal texto As String)
clave = New SecureString
cadena = texto
codifica()
End Sub

‘ Método que codifica el campo cadena dentro de la cadena segura clave.
Public Sub codifica()
For Each letra As Char In cadena
clave.AppendChar(letra)
Next
‘ Hago la clave solo de lectura para que no se pueda modificar por nadie.
clave.MakeReadOnly()

End Sub

‘ Y siguiendo el consejo del Guille, sustituyo el método
‘ toString para que automáticamente me decodifique la
‘ cadena segura almacenada en el campo clave y me lo
‘ devuelva como una cadena de texto.
Public Overrides Function ToString() As String

‘ Como vés no es una tarea directa. Ya que realmente
‘ clave es un puntero que señala una dirección de
‘ memoria a la que se accede por medio de una estructura
‘ tipo IntPtr.
Dim bstr As IntPtr = Nothing
bstr = Marshal.SecureStringToBSTR(clave)
cadena = Marshal.PtrToStringAuto(bstr)

‘ Esto borra la cadena segura sobreescribiendo de ceros
‘ la posición de memoria que ocupaba.
Marshal.ZeroFreeBSTR(bstr)
Return cadena

End Function

End Class

Para mí lo más elegante viene ahora. El cómo usar esta clase.

Instacio la clase mándandole como parámetro el texto que quiero convertir en una cadena segura. Y luego, para recuperar el contenido de la cadena segura, simplemente llamo al método .toString.

Dim texto As New cadenaSegura(TextBox6.Text)
hash.Text = texto.ToString


Que bonita es la POO!!