Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

18 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 13 de septiembre de 2011
El pasado mes de julio publicaba el post “Binding de enums en ASP.NET MVC”, donde analizaba los problemas que podían aparecer cuando estamos intentando bindear tipos enumerados y los datos de entrada contienen valores incorrectos, y planteaba una solución basada en un model binder personalizado.

A raíz de dicho post, el amigo Héctor S. (¡gracias!) me envió una interesante pregunta: ¿por qué no utilizar la anotación System.ComponentModel.DataAnnotations.EnumDataType  para ello?

Y la respuesta corta es: pues también se podría. Con sus particularidades, pero sería posible controlar los valores de entrada a un  enum usando esta anotación.

Empecemos por el principio. EnumDataTypeAttribute es una anotación introducida en .NET 4 que nos permite indicar que una propiedad (no necesariamente de tipo enum) admite exclusivamente valores definidos en un enumerado. Mejor lo vemos con algo de código:

    public enum Sexo
    {
        Hombre = 1,
        Mujer  = 2
    }
 
    [EnumDataType(typeof(Sexo))]
    public int Sexo { get; set; }

En el ejemplo anterior observamos una propiedad Sexo de tipo int, lo que le permite virtualmente alojar cualquier valor entero posible. Sin embargo, el hecho de decorarla con el atributo EnumDataTypeAttribute y asociarla a la enumeración Sexo hará que en la validación de la entidad su valor sea considerado incorrecto si éste no pertenece a los permitidos en ella, en este caso, 1 y 2.

Su uso es interesante, por ejemplo, como método para acercar representaciones de la información. Por ejemplo, si la propiedad Sexo está mapeada hacia un campo de base de datos, es bastante habitual que éste sea de tipo entero, por lo que el hecho de declararla en la entidad como int facilita el movimiento de datos entre uno y otro. Al decorarla con EnumDataType lo que hacemos simplemente es asegurar que contendrá un valor correcto conforme al enumerado, pero ojo, siempre que la entidad sea validada considerando sus anotaciones (como ocurre durante el binding).

Y volviendo al tema del post, entonces, ¿por qué no utilizamos este método para asegurar la validez de los datos en el post al que hacía referencia, en lugar de montar un binder personalizado?

Pues el motivo principal sería la pereza. Realmente, me parece demasiado trabajoso el tener que decorar cada propiedad enum del modelo con una declaración tan redundante como la siguiente:

    public class Persona
    {
        public string Nombre { get; set; }
 
        [EnumDataType(typeof(Sexo))]
        public Sexo Sexo { get; set; }
 
        ...
    }

A ver, si estoy declarando una propiedad de tipo Sexo, me resulta pesado tener que decirle algo más arriba que ésta es un tipo de datos enumerado de tipo Sexo.

Pero bueno, salvando este incómodo detalle, EnumDataType  es una buena fórmula para controlar la corrección de los valores de entrada, y sobre todo muy cómoda si la propiedad parámetro a actualizar es de un tipo no enum, como un int:.


    [EnumDataType(typeof(Sexo))]
    public int Sexo { get; set; }


Su uso aporta, además, otras posibilidades interesantes. Por ejemplo, sería posible crear editores personalizados sobre el tipo int que, basándose en este atributo, mostraran a nivel de vista desplegables u otros controles de selección de forma automática.

Es importante tener en cuenta que, a diferencia de mi enfoque, la comprobación del atributo se realiza durante el proceso de validación, que es posterior al binding en sí. La ventaja de esto es que se integra de forma natural en dicho proceso (por ejemplo, ModelState.IsValid retornará falso si hemos intentado introducir un "3" en Sexo), pero también pueden producirse errores previos generados por el propio binder  si no es capaz de realizar la transformación de forma automática (por ejemplo, al intentar un valor textual no presente en la enumeración, como 'Gato'), que de la otra forma sí sería posible controlar.

Publicado en: Variable not found.
lunes, 12 de septiembre de 2011
Estos son los enlaces publicados en Variable not found en Facebook y Twitter desde el lunes, 05 de septiembre de 2011 hasta el domingo, 11 de septiembre de 2011. Espero que te resulten interesantes. :-)
Y no olvides que puedes seguir esta información en vivo y en directo desde Variable not found en Facebook, o a través de Twitter.

Publicado en: Variable not found
miércoles, 7 de septiembre de 2011
Hace un par de días comentaba la aparición de Universal ASP.NET Providers, un componente que incluye proveedores de membership, roles, profiles y estado de sesión capaces de funcionar con todas las versiones de SQL Server desde la 2005, ediciones express, SQL Azure y SQL Compact 4.0, y utilizables en cualquier aplicación ASP.NET, ya sea Webforms o ASP.NET MVC.

En este post vamos a ver un ejemplo ómo podemos utilizar este nuevo componente para montar en pocos segundos el sistema de membresía, roles y perfiles de una aplicación web utilizando SQL Compact Edition, algo que por otra parte no es una idea nada descabellada para sitios de pequeño calibre. Recordad que esta edición de SQL Server no requiere un servicio funcionando en el servidor (se ejecuta en el mismo proceso que la aplicación web), por lo que puede resultar muy apropiada para su uso en pequeños sitios donde no se justifica la implantación de sus hermanas mayores (express o superiores).

1. Instalamos el tooling en Visual Studio 2010 SP1

Lo primero que vamos a hacer es instalar las herramientas de SQL Compact Edition para el Visual Studio. Éstas las podéis descargar desde este enlace, aunque antes debéis aseguraros de tener instalado el Service Pack 1 de Visual Studio.

Esto no es estrictamente necesario si no pensamos crear o acceder a la base de datos desde Visual Studio, aunque en cualquier caso es recomendable para poder echar un vistazo a la estructura y datos más adelante.

2. Creamos una aplicación web

Creamos ahora una aplicación Web desde Visual Studio. No importa si es ASP.NET MVC o WebForms: en la pila de tecnologías estamos un nivel por abajo, directamente jugando con características de ASP.NET, que, como sabéis, son comunes a ambos frameworks.

Creando la nueva aplicación web ASP.NETPara ilustrar nuestro ejemplo crearemos una aplicación Webforms seleccionando la plantilla “Aplicación Web ASP.NET” en el cuadro de diálogo de nuevo proyecto del IDE, pero podríamos perfectamente elegir la “Aplicación web de ASP.NET MVC” y todo sería exactamente igual.

3. Descargamos de Nuget los componentes que necesitamos

NugetPara lograr nuestros objetivos sólo necesitaremos dos paquetes:
  • el proveedor de datos SQL CE, que nos permitirá conectarnos a esta base de datos y acceder a su información ya sea utilizando directamente las clases de ADO.NET como Entity Framework,
  • el paquete de Proveedores Universales para ASP.NET, que creará la abstracción sobre el origen de datos concreto y nos permitirá trabajar virtualmente con cualquier motor relacional (aunque, como comentaba en el post anterior, por las pruebas que he hecho de momento no sea así). 
Desde la consola de Nuget podemos conseguirlo así:

PM> Install-Package System.Web.Providers
[...]
Successfully installed 'System.Web.Providers 1.0.1'.

PM> Install-Package SqlServerCompact
[...]
Successfully installed 'SqlServerCompact 4.0.8482.1'.

Si en cambio sois más de utilizar el GUI, podéis buscar en la galería los paquetes “ASP.NET Universal Providers” y “SqlServerCompact”:

Instalando los componentes con Nuget

4. Modificamos la cadena de conexión

El proceso de instalación del paquete de proveedores habrá modificado nuestro web.config, dejándolo listo para su utilización con SQL Express. Como no es esto lo que queremos, acudimos a este archivo y modificamos la cadena de conexión usada por los proveedores:

<connectionStrings>
   <add name="DefaultConnection"
      connectionString="Data Source=|DataDirectory|\Datos.sdf;"
      providerName="System.Data.SqlServerCe.4.0" />
</connectionStrings>

Observad que estamos indicando que el proveedor de datos es SqlServerCe (lo hemos descargado previamente usando Nuget), y que la base de datos se llamará datos.sdf y estará ubicada en la carpeta App_Data del proyecto.

De forma opcional, podemos aprovechar el momento para limpiar un poco el web.config, eliminando líneas que vienen en la plantilla de proyectos por defecto, pero que ya no vamos a necesitar.

De limpieza por el web.config

5. ¡Y esto es todo!

Pues sí, eso es todo lo que necesitamos hacer. En este momento ya tenemos configurados los proveedores de membresía, roles y perfiles. De hecho, dado que las plantillas de proyecto tanto para MVC como para Webforms ya incluyen un sistema de autenticación y registro básico, podemos directamente ejecutarla y utilizar sus funcionalidades para registrarnos y autenticarnos en el sistema:


Registro de usuarios en ASP.NET Webforms

Herramienta de administración de ASP.NETAsimismo, dado que se están utilizando mecanismos estándar en el framework, podemos utilizar la propia herramienta de gestión de ASP.NET para crear los usuarios, asignarles funciones o definir reglas de acceso por carpetas. Como ya sabéis, esta utilidad viene incluida de serie en el framework, y podemos acceder a ella a través del menú “Proyecto > Configuración de ASP.NET” de Visual Studio o pulsando sobre un icono que aparece en el explorador de soluciones.

Eso sí, para comenzar a definir roles y asignarlos a usuarios es necesario activar previamente el proveedor de roles (DefaultRoleProvider), ya sea desde la herramienta de administración, bien añadiendo en el nodo <RoleProvider> del web.config el atributo enabled="true".

De la misma forma, podemos activar la persistencia del estado de sesión sobre la misma base de datos estableciendo el atributo mode="Custom" en el nodo <sessionState> (por defecto está configurado como "InProc" ).

En cualquier caso, una vez accedamos a alguno de estos proveedores, podremos observar que se ha creado de forma automática la base de datos llamada Datos.sdf en la carpeta App_Data. Por supuesto, también podríamos haber indicado el nombre de un base de datos existente (creada por ejemplo desde el mismo VS) y el sistema habría creado únicamente las tablas e índices usados por los proveedores sin afectar al resto de objetos.

Recapitulando: si ya tenemos el tooling y el proveedor de datos para SQLCE en un proyecto, lo único que tenemos que hacer es, en primer lugar, descargar a través de Nuget el paquete de Proveedores Universales de ASP.NET, y a continuación ajustar la cadena de conexión en el web.config. Más sencillo, imposible.

He dejado en Skydrive una solución de ejemplo con un proyecto Webforms y otro MVC para que podáis probarlo de forma sencilla. En la base de datos hay un usuario creado (jmaguilar con clave jmaguilar, aunque podéis registraros desde las propias aplicaciones); para que podáis ver cómo se comporta el sistema de autenticación y membresía, no se permite el acceso a las páginas “Acerca de” a usuarios no identificados previamente.

Publicado en: Variable not found.
martes, 6 de septiembre de 2011
ASP.NETPoco antes de verano comentábamos de pasada la aparición de su versión alfa, y ya desde mediados de agosto tenemos aquí la versión final de ASP.NET Universal Providers, un componente que incluye proveedores de membership, roles, profiles y estado de sesión capaces de funcionar con todas las versiones de SQL Server desde la 2005, ediciones express, SQL Azure y SQL Compact 4.0, y utilizables en cualquier aplicación ASP.NET, ya sea Webforms o ASP.NET MVC.

Lo interesante que tiene el ensamblado System.Web.Providers, que así es como se distribuye el componente, es que podemos modificar el motor de persistencia sobre el que trabajan simplemente tocando la cadena de conexión en el web.config, evitándonos el tener que crear proveedores en cuanto nos salíamos de los provistos por defecto en la plataforma (SQL Server). O en otras palabras, tenemos aquí un proveedor para gobernarlos a todos ;-)

Como no podría ser de otra forma, la distribución del paquete de proveedores se realiza a través de Nuget, por lo que su instalación y puesta en marcha es sencillísima.

Instalando los proveedores universales con Nuget
Una vez descargado e instalado el paquete “ASP.NET Universal Providers”, además de añadirse el ensamblado System.Web.Providers y sus correspondientes referencias al proyecto, veremos que en el web.config se ha incluido una cadena de conexión, llamada “DefaultConnection”, que es la que será utilizada por estos nuevos proveedores. Por defecto podremos comprobar que esta conexión está configurada para trabajar sobre una instancia de usuario de SQL Express, pero simplemente modificándola podremos hacer que funcione sobre ediciones superiores de SQL Server, SQL Azure o SQL Compact.

Un detalle importante es que, para evitar daños colaterales, el proceso de instalación no elimina la cadena de conexión previa (esa que vemos con la denominación “ApplicationServices”), ni la configuración de proveedores previa: simplemente añade el nuevo proveedor y lo establece por defecto, por lo que podemos eliminar tranquilamente esas configuraciones que ya no utilizamos.

Eliminando del Web.config líneas que ya no usamos
Tablas creadas por los proveedoresUna vez configurada correctamente la cadena de conexión (“DefaultConnection”) ya no será necesario tocar nada más; el sistema se encargará de crear las tablas necesarias para almacenar la información de usuarios, roles, perfiles, e incluso para hacer persistente el estado de sesión (si utilizamos el proveedor incluido en este componente); además, si no existe la base de datos, será capaz de crearla automáticamente si tenemos permisos para ello.

Como nota negativa, seguro que habéis pensado que ya que es posible modificar el proveedor de datos a nivel de archivo de configuración, parece lógico que podamos utilizar cualquier origen de datos disponible, ¿verdad? Pues no necesariamente. He probado con el conector MySQL y no ha habido forma de echar a andar estos proveedores debido a un problema de incompatibilidad del tipo “image” en los metadatos. No sé si se debe a limitaciones del Universal Provider, o bien se trata de algún problema en la implementación del conector MySQL.

Sin duda, es un avance interesante que puede ahorrarnos bastante tiempo en esa tarea tan molesta que es montar la infraestructura de membresía y seguridad de nuestras aplicaciones. Y además, como comentaba Hanselman en su momento, estos proveedores es posible que formen parte de la próxima versión del framework, por lo que habrá que estar atentos a ellos.

En un próximo post os mostraré un ejemplo práctico, cómo utilizar este componente para poner en marcha el sistema de membership, roles y perfiles sobre una base de datos SQLCE.

Publicado en: Variable not found.
lunes, 5 de septiembre de 2011
Para abrir la temporada, ahí van los enlaces publicados en Variable not found en Facebook y Twitter desde el lunes 29 de agosto de 2011 hasta el domingo, 04 de septiembre de 2011.

Espero que te resulten interesantes. :-)
Y no olvides que puedes seguir esta información en vivo y en directo desde Variable not found en Facebook, o a través de Twitter.

Publicado en: Variable not found

domingo, 4 de septiembre de 2011
Vamos allá¡Qué poco han durado! Supongo que estos días no hay afirmación más repetida por todos los que volvemos de vacaciones. Y la sensación más habitual, sin duda, el sabor agridulce de saber que han acabado unos días estupendos. Pero que nos quiten lo bailao, eh? ;-)

El caso es que ya estamos aquí de nuevo. Descansados, oxigenados, ilusionados y listos para enfrentarnos a otro emocionante año que seguro nos traerá grandes alegrías :-)

Por empezar con novedades, habréis notado le he dado un lavado de cara a la plantilla del blog, que ya se le iban notando los años. He sustituido el layout líquido por uno de ancho fijo, más apropiado para facilitar la lectura en las ya extendidas pantallas panorámicas, he simplificado algo el código pasando a usar características de CSS3 (lo siento por los que aún navegáis en galeones ;-)), y he reestructurado la columna derecha, pasando a segundo plano la publicidad de los laterales a pesar de los vastos ingresos que generaban, y potenciando la vertiente social y de comunidad del blog.

Y dicho esto, ¡queda inaugurada la temporada 2011-2012 de Variable not found!

Como siempre, nos vemos por aquí.