viernes, 24 de septiembre de 2010

EF4 Code First, MVC2 y Unity para atarlo todo un poco…

Buenas! No soy ni mucho menos un experto en EF (es más, me acabo de poner), como pueda serlo p.ej. Unai, pero desde que Scott Guthrie publicó un post sobre EF Code First he empezado a mirar algunas cosillas.

Resumiendo rápidamente EF Code First nos permite desarrollar nuestra capa de acceso a datos codificando primero las clases, clases que son POCO. Eso nos permite conseguir lo que se conoce como persistance ignorance (o que las clases que nos representan los datos sean agnósticas sobre cualquier tecnología de acceso a datos).

Que quede claro que Code First no es la única manera de usar objetos POCO en EF: Unai y Alberto hablan del tema aquí y aquí. Y dad por seguro que ellos conocen EF mucho más que yo :)

Lo que os quiero comentar es como se puede montar EF Code First en una aplicación MVC2 para poder usar el patrón Repository y Unit Of Work, de forma que los controladores no deban saber nada del mecanismo subyacente de acceso a datos (es decir, los controladores ignoran completamente que están usando EF).

1. Rápida, rapidísima introducción a EF Code First

Usar EF Code First es muy sencillo. En el post de Scott Guthrie está todo explicado paso a paso, pero resumiendo podríamos decir que me puedo crear una clase tal que:

public class Persona
{
public int PersonaId {get; set;}
public string Nombre {get; set;}
}





Esta clase nos permitiría acceder a datos almacenados en una tabla con los campos PersonaId y Nombre (EF Code First es capaz de crear la BBDD a partir del modelo de objetos). Para acceder a la bbdd creamos un objeto derivado de DbContext:




public class MyDatabase : DbContext
{
public DbSet<Persona> Personas {get; set;}
}





Y a partir de aquí instanciamos un objeto MyDatabase y lanzamos consultas linq contra la propiedad Personas… :)



2. Patrón repositorio y Unit of work



Esos patrones están explicados por activa y por pasiva en muchos sitios. P.ej. aquí está el patrón repositorio y aquí el Unit of Work (UoW). Básicamente entendemos que el repositorio es una colección de objetos en memoria y que el patrón UoW sincroniza todos los cambios hechos en memoria hacia la base de datos.



Supongamos estos dos interfaces para definir ambos patrones:




public interface IRepository<TEntity> where TEntity : class
{
IQueryable<TEntity> AsQueryable();
IEnumerable<TEntity> GetAll();
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> where);
}






public interface IUnitOfWork
{
void Commit();
}





Mi repositorio es de sólo lectura (no hay métodos Add ni Remove ni nada, pero todo es añadirlos) y el Unit of Work lo único que tiene es el método Commit() para sincronizar los cambios hechos en los repositorios y mandarlos todos a la base de datos.



EF Code First, implementa de per se el patrón Unit Of Work (a través de DbContext) y también el patrón repositorio a través de DbSet<>, pero recordad que yo quiero “agnostizarme” al respecto de EF, por eso creo las interfaces y ahora debo crear implementaciones de ellas para EF:




public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
private IDbSet<TEntity> _dbSet;

public Repository(IDbContext objectContext)
{
_dbSet = objectContext.Set<TEntity>();
}
public IQueryable<TEntity> AsQueryable()
{
return _dbSet;
}
public IEnumerable<TEntity> GetAll()
{
return _dbSet.ToList();
}
public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> where)
{
return _dbSet.Where(where);
}
}






public class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly IDbContext _objectContext;

public UnitOfWork(IDbContext objectContext)
{
_objectContext = objectContext;
}

public void Dispose()
{
if (_objectContext != null)
{
_objectContext.Dispose();
}
GC.SuppressFinalize(this);
}

public void Commit()
{
_objectContext.SaveChanges();
}
}





La única “complicación” es en la implementación de UnitOfWork, que en el constructor uso un objeto de tipo IDbContext, pero esta interfaz no existe en EF: me la he inventado yo, para poder realizar DI luego cuando use Unity. La interfaz IDbContext es muy simple:




public interface IDbContext : IDisposable
{
IDbSet<T> Set<T>() where T : class;
int SaveChanges();
}





Me permite obtener un IDbSet de entidades de tipo T y el método SaveChanges para persistir los cambios realizados en este contexto hacia la BBDD.



3. Uso de todo esto…



Para usar directamente un repositorio me basta con instanciarlo, pasándole como parámetro el IDbContext. Pero recordad que la clase DbContext de EF Code First no implementa IDbContext (que me lo he inventado yo), así que uso el patrón Adapter para traducir los objetos DbContext a IDbContext:




public class DbContextAdapter : IDbContext
{
private readonly DbContext _context;
public DbContextAdapter(DbContext context)
{
_context = context;
}
public void Dispose()
{
_context.Dispose();
}
public IDbSet<T> Set<T>() where T : class
{
return _context.Set<T>();
}
public int SaveChanges()
{
return _context.SaveChanges();
}
}





Ahora sí que ya puedo crear un repositorio:




IDbContext ctx = new DbContextAdapter(MyDatabase);  // MyDatabase deriva de DbContext
var rep = new Repository<Persona>(ctx);
var personas = rep.FindAll();





Para usar el Unit of Work vinculado a un contexto haríamos lo mismo.



4. Añadiendo IoC a todo esto…



Ahora que ya vemos como podemos usar nuestro repositorio, vamos a ver como Unity nos ayuda a tener IoC y independizarnos realmente de EF.



Primero podríamos registrar las implementaciones concretas de IRepository y IUnitOfWork:




// Container es el IUnityContainer
Container.RegisterType(typeof(IRepository<>), typeof(Repository<>));
Container.RegisterType<IUnitOfWork, UnitOfWork>();





Ahora debemos mapear IDbContext a DbContextAdapter (porque para instanciar tanto IRepository como IUnitOfWork les debemos pasar un IDbContext. Podríamos usar lo siguiente:




Container.RegisterType<IDbContext, DbContextAdapter>();





Este RegisterType está bien, pero el problema nos viene cuando vemos que el constructor de DbContextAdapter tiene un objeto DbContext. Eso significaría que Unity nos crearía un objeto de la clase DbContext y no de la clase derivada MyDatabase, para instanciar los objetos DbContextAdapter. Nota: Una solución sería que la clase DbContextAdapter tuviese en su constructor un objeto que no fuera DbContext sinó MyDatabase pero eso entonces limita la reutilización de todo lo que estamos haciendo!



Por suerte no estamos perdidos! Unity incorpora un mecanismo mediante el cual le podemos decir como crear un objeto de una determinada clase. En mi post sobre Unity 2.0, hablé de las Injection Factories. La idea es decirle a Unity que cuando necesite un objeto de la clase indicada, en lugar de crearlo tal cual use una factoría nuestra.



Es decir podemos hacer una factoría para crear DbContext que en lugar de un DbContext devuelva un MyDatabase, y Unity usará dicha factoría cada vez que deba crear un DbContext:




Container.RegisterType<DbContext>(new InjectionFactory(x => new MyDatabase()));





Listos! Con esto cuando Unity deba pasar a DbContextAdapter un objeto DbContext (como indica el constructor) creará realmente un objeto MyDatabase.



Ahora si que ya puedo hacer:




var rep = Container.Resolve<IRepository<Persona>>();









5. Y finalmente… MVC2



Para integrar esto dentro de MVC2 es muy sencillo: como siempre que queramos inyectar IoC en los controladores lo que debemos tocar es… la factoría de controladores:




public class UnityControllerFactory : DefaultControllerFactory
{
private readonly IUnityContainer _sl;

public UnityControllerFactory(IUnityContainer sl)
{
_sl = sl;
}

protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
IController controller = _sl.Resolve(controllerType);
return controller;
}
}





Y como siempre establecerla en el Global.asax:




UnityControllerFactory slcf = new UnityControllerFactory(container);
ControllerBuilder.Current.SetControllerFactory(slcf);





Y listos! Ahora si que hemos llegado al punto final. Por fin podemos declarar un controlador tal que:




public class PersonasController : Controller
{
private IRepository<Persona> _rep;

public HandController(IRepository<Persona> rep)
{
_rep = rep;
}
}





Y empezar a trabajar usando el repositorio! :)



Fijaos que en este punto (el controlador) no tenemos nada que nos ate a EF: el repositorio es una interfaz y las clases que usa el repositorio son objetos POCO.



6. Y para terminar (pero NO lo menos importante)…



Cuando trabajamos con aplicaciones web, es recomendable que los contextos de base de datos tengan una duración (lifetime) de request (se les llama objetos per-request): es decir si durante una misma petición se necesitan dos repostorios, estos dos repositorios deben de compartir del contexto de base de datos. Con lo que tenemos ahora no sucede esto, ya que cada vez que Unity deba crear un Repository<> creará su DbContextAdapter asociado que a su vez creará un DbContext (MyDatabase) nuevo. Ese comportamiento no es el desado.



Por suerte Unity tiene un mecanismo muy bueno para poder establecer cada cuando debe el contenedor crear un objeto de un tipo determinado: los lifetime managers. Una solución es crearse un HttpRequestLifetimeManager, de forma que los objetos sólo persistirán durante la misma petición y usar este lifetime manager cuando hagamos el RegisterType de DbContext.



En http://unity.codeplex.com/Thread/View.aspx?ThreadId=38588 tenéis una implementación de un HttpRequestLifetimeManager, junto con una interesante aportación sobre el uso (en su lugar) de contenedores hijos que mueran a cada request, que tengan los objetos registrados como singletons y eliminar el contenedor hijo (con Dispose()) al final de cada request. Esto tiene la ventaja de que se llamaría a Dispose() de los objetos contenidos (en esta segunda aproximación es el contendor hijo el que tiene un ciclo de vida per-request).



7. Referencias



Los siguientes posts contienen más información al respecto:




  1. Entity Framework POCO (EF4): Generic Repository and Unit of Work Prototype. Este es el post que me ha servido de inspiración y de ayuda. Tiene una continuación (Unity Extension for Entity Framework POCO Configuration, Repository and Unit of Work) donde comenta el uso de Unity. Estos dos posts son de lectura imprescindible, aunque por un lado haya tenido que modificar algunas cosillas para que funcione con la CTP4 de EF Code first y por otro en el tercer post utilize una StaticFactoryExtension en lugar de una Injection Factory (supongo que usa Unity 1.2 que no soporta Injection Factories). Este tercer post utiliza una aproximación genial que es el uso de una extensión de Unity para configurar todos los mappings para los objetos de EF. Repito: lectura imprescindible.


  2. Los posts de Scott Guthrie sobre EF Code First:

    1. http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx


    2. http://weblogs.asp.net/scottgu/archive/2010/07/23/entity-framework-4-code-first-custom-database-schema-mapping.aspx


    3. http://weblogs.asp.net/scottgu/archive/2010/08/03/using-ef-code-first-with-an-existing-database.aspx





Un saludo!!! :)



PD: Como no… esto es un crosspost desde mi blog en geeks.ms

viernes, 10 de septiembre de 2010

ASP.NET MVC – Formato de salida según Content-Type

El otro día escribí un post donde vimos como mostrar una vista en PDF o HTML en función de una URL del tipo /controlador/accion(formato)/parámetros. El post estaba centrado básicamente en la tabla de rutas y cómo la URL clásica de ASP.NET MVC /Controlador/Accion/Parámetros no es una obligación sinó básicamente una convención.

Hadi Hariri realizó un comentario, muy interesante a mi jucio. Venía a decir que antes que añadir en la ruta el parámetro formato es mejor usar el campo Accept de la request. Copio literalmente: “La tercera opcion, que lo hace más transparente al usuario y además está en acorde a ReST, es la de usar las el ContentType en la petición, que es lo que yo normalmente hago.

Si quieres exponer una API lo más ReST posible en ASP.NET MVC y que tenga salidas en distintos formatos, sin duda deberías tener en cuenta la sugerencia de Hadi.

1. La cabecera de la petición http

Cuando un cliente envía una petición http a un servidor, que contiene una cabecera con varios parámetros. Dicha cabecera tiene varios campos que permiten especificar determinadas opciones que el cliente desea. Uno de esos campos es el campo Accept que permite indicar que formatos de respuesta acepta el cliente y en que orden.

P.ej. si hago una petición con Firefox a http://www.google.es, el contenido del campo Accept de la cabecera que firefox envia es (lo acabo de mirar con Firebug):

text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Que podríamos interpretar (más o menos) como: Mis formatos preferidos son text/html y application/xhtml+xml, si no puedes en ninguno de esos dos, envíamelo en application/xml y si no puedes, pues me tragaré lo que me mandes.

El valor exacto de dicha cabecera depende del browser… P.ej. IE8 para la misma peticion envia el siguiente valor en Accept (lo acabo de mirar con Fiddler):

image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*

Por lo tanto vemos como en el campo Accept el cliente nos dice que formatos de respuesta entiende (y en que orden los prefiere).

2. Acceso a la cabecera desde ASP.NET MVC

Imaginad que tenemos un controlador que puede devolver datos en dos formatos: XML y JSON. Y queremos usar el campo Accept de la cabecera http que envíe el cliente para devolver los datos en uno u otro formato.

Acceder a la cabecera http desde un controlador es extremadamente sencillo, usando Request.AcceptTypes, que es un array con todos los campos de la cabecera accept.

3. Devolver datos en formato XML

ASP.NET MVC no trae ningún mecanismo incluído para devolver datos en formato xml, lo que me va de coña para enseñaros como nos podemos crear un ActionResult propio:

public class XmlActionResult : ActionResult
{
private readonly object _data;
public XmlActionResult(object data)
{
_data = data;
}
public override void ExecuteResult(ControllerContext context)
{
XmlSerializer ser = new XmlSerializer(_data.GetType());
context.HttpContext.Response.ContentType = "text/xml";
ser.Serialize(context.HttpContext.Response.OutputStream, _data);
}
}





Crear un ActionResult propio es trivial: deriváis de ActionResult y implementáis el método abstracto ExecuteResult y en él hacéis lo que sea necesario (usualmente interaccionar con la Response). En este caso simplemente serializo el objeto que se le pasa con el serializador estándard de .NET. Ah si! Y pongo el content-type a text/xml que es el content-type usado para documentos en XML.



Yo suelo acompañar los ActionResults propios con un método extensor para los controladores, para llamarlos de forma similar a los ActionResults que vienen en el framework. Mi método extensor (trivial) es:




public static class ControllerExtensions
{
public static XmlActionResult Xml(this ControllerBase @this, object data)
{
return new XmlActionResult(data);
}
}





Y ahora ya puedo realizar la acción de mi controlador:




public ActionResult List()
{
var data = new GeeksModel().GetAllGeeks();
return Request.AcceptTypes.Contains("application/json") ?
(ActionResult)Json(data, JsonRequestBehavior.AllowGet) :
(ActionResult)this.Xml(data);
}





Simplemente pregunto si está el accept application/json(*) (que parece ser el content-type para JSON). Si lo está envío los datos en json y si no pues en xml! Si abrimos un navegador y vamos a /Geeks/List veremos los datos en XML porque ningún (bueno, ni FF ni IE que son los que he probado :p) envían application/json en el accept de la request.




(*) Ok, acepto que esta pregunta no es del todo correcta: debería mirar si application/json está preferido antes que text/xml (por si me manda ambos). Igual que teoricamente, debería comprobar si no me manda ninguno de los dos, y si es el caso devolver un error 406.




4. Un detallito final…



Bueno, eso parece funcionar, pero lo que chirría un poco es tener que meter este if() para comprobar en cada acción de cada controlador si la request contiene application/json o no y serializar el resultado en JSON o en XML.



Para evitar esto he encontrado dos alternativas en la red:




  1. Usar otro action result y que sea el action result quien decida si serializar los datos en XML o en JSON. Es decir, crearnos un JsonOrXmlActionResult, devolver siempre una instancia de este action result desde los controladores y en el ExecuteResult, preguntar por el campo accept y serializar en un formato en otro. Esta aproximación la he visto en el post “Create REST API using ASP.NET MVC that speaks both Json and plain Xml” del blog de Omar Al Zabir.


  2. Otra aproximación totalmente distinta (pero muy interesante) que usa un action filter para ello. Está en el blog de Aleem Bawany, en el post “ASP.NET MVC – Create easy REST API with JSON and XML”.



Os recomiendo la lectura de estos dos posts.



Un saludo y gracias a todos, especialmente a Hadi Hariri quien con su comentario anterior, ha motivado este post! :)



PD: Como siempre, esto es un crosspost desde mi blog en geeks.ms! Pásate por allí mejor, que somos más!

miércoles, 8 de septiembre de 2010

Subir ficheros al servidor en ASP.NET MVC

Buenas! Hoy voy a responder alguna pregunta que me he encontrado en alguna vez, y es como subir ficheros al servidor usando MVC2.

La verdad es que con ASP.NET MVC2 subir ficheros al servidor es extremadamente simple. Vamos a empezar viendo el código de una vista que permite subir un fichero al servidor, junto con una descripción adicional. La vista básicamente contiene un  <form> como el siguiente:

<form action="<%: Url.Action("Upload") %>" enctype="multipart/form-data" method="post">
<label for="descripcion">Descripción del fichero:</label>
<input type="text" id="descripcion" name="descripcion" />
<br />
<label for="fichero">Fichero:</label>
<input type="file" name="fichero" size="40">
<br />
<input type="submit" value="Enviar" />
</form>





Fijaos que es HTML puro y duro, aunque el tag <form> lo podeis generar con Html.BeginForm() si queréis. La clave es añadir el atributo enctype con el valor multipart/form-data. Como se menciona en la especificación sobre formularios del W3C, el valor de multipart/form-data es el que debe usarse cuando se quieran enviar al servidor datos binarios.



El <input type=”file”> es el control HTML que nos permite seleccionar un fichero para enviar.



Y desde el controlador? Pues sencillo, en este caso mi formulario tiene dos parámetros (descripcion y fichero), por lo que necesitaré que la acción del controlador tenga esos dos parámetros. El parámetro descripcion es un string, pero el parámetro fichero… que és?



Pues bien ASP.NET MVC es capaz de ver que el parámetro fichero es un fichero que se ha subido al servidor y sabe mapearlo a un objeto de la clase HttpPostedFileBase. Esta clase nos da acceso no sólo al contenido del fichero subido, sinó a más información (su content-type, su tamaño, el path completo desde donde se ha subido,…).



El método del controlador queda pues, así de sencillo:




[HttpPost]
public ActionResult Upload(string descripcion, HttpPostedFileBase fichero)
{
fichero.SaveAs(Path.Combine(@"d:\temp", Path.GetFileName(fichero.FileName)));
return View();
}





Fijaos en los dos parámetros string y HttpPostedFileBase. El método simplemente se guarda una copia del fichero subido en d:\temp, pero obviamente aquí podéis hacer lo que queráis.



Y listos! No hay que hacer nada más… qué, sencillo, no??? :)



Un saludo



PD: Esta técnica no es ajax, eso significa que mientras se está subiendo el fichero al servidor, la aplicación web no responde (el browser está haciendo la petición). Existe un mecanismo para realizar subidas de ficheros en background, aunque no es directo debido a que con XMLHttpRequest (el objeto del naveagador que hace posible ajax) no se pueden subir ficheros. Si estáis interesados en el siguiente post de John Rudolf se muestra como realizar un upload de fichero en ajax usando jQuery y el form plugin!




PD2: Como no, eso es un crosspost desde mi blog en geeks.ms!

miércoles, 25 de agosto de 2010

Opinión: bool es sólo para true/false

Saludos a todos! Tanto a los que estéis trabajando, cómo aquellos que estando de vacaciones seais tan frikis que leais geeks.ms! :)

Hoy quiero hablar un poco sobre bool. Puede parecer un tipo de datos aburridote: a fin de cuentas sólo puede tener dos valores, pero precisamente ahí radica su gracia y de eso os quería contar. La idea del post es muy simple: bool es sólo para true/false.

Por ejemplo, en los arcanos tiempos en que un servidor usaba Visual C++ 6 para el desarrollo de aplicaciones windows, en las MFCs había un método muy divertido llamado UpdateData (que por lo que veo aún está). MFC tenía una cosa muy buena que era la posibilidad de realizar bindings entre variables de la clase que representaba la ventana (usualmente una clase derivada de CWnd) y los controles que contenía dicha ventana. Eso, ahora, puede parecer una chorrada pero por aquel entonces era una auténtica pasada.

El método UpdateData era el que se encargaba de realizar dicho binding. Se llamaba con un parámetro BOOL que si valía TRUE significaba que se pasaban los datos de los controles a las variables y si valía FALSE pues era al revés: se pasaban los datos de las variables a los controles. Eso lo acabo de leer ahora en la MSDN, pero cuanda usaba MFC lo tenía que leer a menudo: nunca me acordaba cual era el significado de TRUE y FALSE en este contexto… En el fondo el parámetro de dicha función no es true/false es “BindingDeControlesAVariables” o “BindingDeVariablesAControles”, es decir un enum con dos opciones.

Y a eso me refiero en este post: un enum con dos opciones no es un booleano, aunque en ambos casos tengamos sólo dos valores posibles. Establecer arbitrariamente un valor a true y otro a false sólo hace que la gente se confunda.

Que código creéis que es más legible?

Fichero.Abrir("foo.txt",true);





O bien:




Fichero.Abrir("foo.txt",ModoApertura.Lectura);





En el primer caso, el segundo parámetro es un bool que si vale true se abre el fichero para lectura y si es false, pues se abre para escritura. Pues vale, pero es una decisión arbitraria y cuando alguien deba usar Abrir probablemente deba consultar que hace exactamente este parámetro bool (y lo mismo si alguien revisa código).



Pero no sólo es por legibilidad de código… Podéis asegurar que dos opciones serán siempre dos opciones? Me explico, y esta vez, como nadie (ni mucho menos yo) está libre de pecado, con un ejemplo de cosecha propia.



En un framework que estamos desarrollando para permitir desarrollos de aplicaciones con ciertas características hay una propiedad de una clase (llamésmola Aplicacion) que indica si cuando se va a la pantalla anterior (las aplicaciones tienen navegación parecida a la de un browser) se debe destruir la vista de la cual se proviene o bien dicha vista se mantiene en memoria.



En su momento implementamos dicha propiedad con un bool (true = destruir la vista, false = no destruirla). Y estuvo bien… hasta cierto día.



Cierto día, nos vimos en la necesidad de que en ciertas aplicaciones la vista se debía destruir sólo si no contenía datos (en caso contrario se podía reaprovechar). A priori esto dependía de cada aplicación. Y ahí tuvimos el problema: como mapeamos esto en nuestra propiedad booleana? Porque ahora teníamos tres valores:




  1. No destruir la vista


  2. Destruir la vista siempre


  3. Destruir la vista sólo si no tiene datos



Nosotros solucionamos el problema añadiendo una segunda propiedad que fuese “que tipo de destrucción de vistas se quería”, y lo hicimos así, simplemente porque todas estas propiedades estaban serializadas en XML (en archivos que algunos ya estaban en producción), por lo que la propiedad original debía ser siendo bool. Total, ahora tenemos dos propiedades a establecer para un mismo comportamiento lo que es susceptible de errores y de confusión. Y todo por no haber usado en su momento un enum :)



Así pues, un consejo: cuando creeis propiedades bool, aseguraos de que realmente un bool es lo que necesitais y no un enum (aunque sea con dos opciones!).



Un saludo!!!!



PD: Esto es (como siempre) un crosspost desde mi blog en geeks.ms!

sábado, 14 de agosto de 2010

Opinión: De los atributos y su uso…

Sí, ya sé: estamos en Agosto y lo que más seduce ahora mismo es darse un bañito en la playa y salir de copas a rebentar los mojitos del bar, así que los que podáis hacedlo sin dudar… Total, este post tampoco se largará a ninguna parte luego… :)

Los que no estéis de vacaciones o bien prefiráis leer geeks.ms en pleno Agosto (hay de todo en la viña del señor) a ver que os parece este post… es mi opinión sobre el uso que se da a los atributos y los “problemas” que a mi parecer conlleva dicho uso. Dado que es un post de opinión vuestros comentarios sobre vuestras opiniones serán muy bien recibidos (de hecho siempre lo son, simplemente en este post lo serán más si cabe).

He estado observando en determinados casos un uso de los atributos que no me termina de convencer… Para aclarar conceptos entiendo por atributos aquellas clases que derivan de System.Attribute y que usamos para decorar nuestras clases, métodos, propiedades…

Voy a centrar este artículo de opinión en Data Annotations, pero no es el único caso que tiene este “defecto”…

En mi opinión los atributos deberían representar sólamente metadatos, es decir mera información, sin comportamiento alguno definido… O dicho de otro modo no deberían tener ningún método, sólo propiedades.

Cojamos el siguiente código de ejemplo, que es lo más simple del mundo: una clase, con una sola propiedad decorada con [Required]. Dicho atributo indica que la propiedad que se decora con él debe tener un valor:

class Foo
{
[Required]
public string Bar { get; set; }
}





Bien, ahora dado el siguiente código:




Foo foo = new Foo();
foo.Bar = string.Empty;
bool b = ((RequiredAttribute)foo.GetType().
GetProperty("Bar").GetCustomAttributes(false)[0]).
IsValid(foo.Bar);





Cuál es el valor de b, en este punto?



La respuesta rápida es… depende de la implementación del método IsValid que está en RequiredAttribute. En este caso el valor de IsValid es false, porque string.Empty asume que no es un valor válido.



Y aquí es donde, a mi, me chirría todo un poco… Yo estoy marcando un valor como requerido (usando [Required]) pero no entiendo porque la implementación de Required decide que significa ser requerido dentro de mi aplicación. Es decir el mero de hecho de declararlo como requerido me obliga a una implementación concreta de que signfica “ser requerido”.



En mi lógica de negocio requerido puede significar que no valga null (siendo string.Empty un valor válido, cosa que no acepta el RequiredAttribute). Me diréis que me puedo crear mis propios atributos y tendréis toda la razón del mundo pero entonces si aplico a la propiedad Bar de la clase Foo un atributo mío, estoy cambiando los metadatos de dicha clase… que pasa si la clase es externa o bien quiero usarla en distintos proyectos (donde el concepto de requerido puede ser diferente)?



No se si sería mejor separar RequiredAttribute en dos clases: una que sea el atributo que marque el elemento como requerido y otro que sea “que significa que un elemento sea requerido (es decir el método IsValid)” (dejadme llamar AttributeHandler a estas clases por ponerles nombre). Obviamente el framework debería proporcionar un AttributeHandler asociado a cada atributo y debería darme un mecanismo para que yo pudiese indicar que en mi proyecto el AttributeHandler para la clase RequiredAttribute es la clase que yo quiera…



No sé si me entiende por donde voy… :)



Un (caluroso) saludo a todos!



PD: Un efecto colateral de tener atributos con cierto comportamiento es que estos empiezan a tener dependencias a terceros componentes (imaginaros un atributo tipo [Log]… que usa para generar los ficheros de log?). Y dado que los atributos los crea el CLR eso hace difícil inyectarles dependencias… Si el código que tiene el comportamiento (p.ej. el que hace log) estuviese en otras clases que no se creasen automáticamente por el CLR sería más fácil inyectarles dependencias).



PD2: Esto es un crosspost desde mi blog en geeks.ms (como todos)!

jueves, 29 de julio de 2010

ASP.NET MVC3 – Filtros que no son atributos

Antes que nada una nota: Este post está basado en la preview 1 de ASP.NET MVC3. Todo lo que comento puede cambiar en futuras previews de MVC3.

En el post de ayer comentaba las novedades de ASP.NET MVC3 preview1 y una de las mejoras más interesantes es el soporte de inyección de dependencias para los filtros. Eso se consigue con el uso de una nueva interfaz IFilterProvider y esa interfaz nos trae de regalo, una posibilidad adicional: Tener filtros que no sean atributos.

Veamos un ejemplo y como podríamos usar este nueva capacidad en MVC3.

1. Que queremos?

Queremos poder usar el concepto de filtros de MVC, pero sin usar atributos. Es decir sin tener que decorar los controladores o sus acciones con atributos tipo [Authorization].

Vamos a proporcionar una mini api de configuración, para que pueda configurar los filtros, usando una api fluent:

FluentFilterProvider ffp = new FluentFilterProvider();
ffp.AddForController<HomeController, MyCustomFilter>().ForAction("Index");
ffp.AddForController<HomeController, MyOtherCustomFilter>();





Aquí configuro dos filtros para el controlador Home: Uno para la acción “Index” (MyCustomFilter) y otro para todas sus acciones (MyOtherCustomFilter).



2. Creación del esqueleto de lo que necesitamos



El primer paso es crearnos nuestro propio proveedor de filtros, es decir nuestra clase que implemente la interfaz IFilterProvider. Nada más sencillo que esto:




public class FluentFilterProvider : IFilterProvider
{
public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
return null;
}
}





3. Creación de la interfaz de configuración fluent



La idea es que nuestro proveedor de filtros tenga una colección de IFilterConfigItem y cada IFilterConfigItem tenga la información para saber cuando instanciar el filtro (es decir a que controlador y acción afecta y cual es la clase que implementa el filtro).



Como no sabemos si eso puede complicarse más, definimos una clase FluentFilterProviderConfig que mantenga esta colección:




class FluentFilterProviderConfig
{
private List<FilterConfigItem> _items;

public FluentFilterProviderConfig()
{
_items = new List<FilterConfigItem>();
}

internal ICollection<FilterConfigItem> Items
{
get { return _items; }
}
}





La colección es de objetos de la clase FilterConfigItem, esta clase es la que implementa IFilterConfigItem. Veamos primero como está definido la interfaz IFilterConfigItem:




public interface IFilterConfigItem
{
void ForAction(string actionName);
}





Un solitario método ForAction que nos permite indicar que dicho filtro se aplica a una acción en concreto.



Y ahora veamos la clase FilterConfigItem:




class FilterConfigItem : IFilterConfigItem
{
private Type _filterType;
private Type _controllerType;
private string _actionName;

internal FilterConfigItem(Type tf, Type controllerType)
{
_filterType = tf;
_controllerType = controllerType;
_actionName = null;
}

internal Type ControllerType { get { return _controllerType; } }
internal Type FilterType { get { return _filterType; } }
internal string ActionName { get { return _actionName; } }

public void ForAction(string actionName)
{
_actionName = actionName;
}
}





Dicha clase guarda toda la información requerida:




  • El tipo de la clase que implementa el filtro (_filterType)


  • El tipo del controlador al que se aplica el filtro (_controllerType)


  • El nombre de la acción a la que se aplica el filtro (_actionName). Este valor es opcional (si vale null el filtro se aplicará a todas las acciones).



Tenemos también propiedades para acceder a esta información, pero fijaos que son internal y no forman parte de la interfaz. Esto es porque esas propiedades sólo son para la implementación de la API, no para su uso público.



Finalmente en la clase FluentFilterProvider vamos a guardar un objeto con la configuración y vamos a proporcionar el punto de entrada a la API fluent: el método AddForController:




public class FluentFilterProvider : IFilterProvider
{
private FluentFilterProviderConfig _cfg;

public FluentFilterProvider()
{
_cfg = new FluentFilterProviderConfig();
}

public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
// Ya veremos que metemos aquí...
}

public IFilterConfigItem AddForController<TC, TF>()
where TC : IController
where TF : class
{
FilterConfigItem fci = new FilterConfigItem(typeof(TF), typeof(TC));
_cfg.Items.Add(fci);
return fci;
}
}





Fijaos que el método AddForController crea un objeto FilterConfigItem, lo añade a la colección y lo devuelve. Esta devolución es lo que permite encadenar las llamadas (característica básica de una interfaz fluent).



4. Creación del filter provider



Bien, sólo nos queda terminar de implementar la clase FluentFilterProvider con la implementación del método GetFilters. El código es muy sencillo:




public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
var items = _cfg.Items.Where(x => x.ControllerType == controllerContext.Controller.GetType()
&& (x.ActionName == null || x.ActionName.Equals(actionDescriptor.ActionName)));
foreach (var item in items)
{
var sl = MvcServiceLocator.Current;
var filterInstance = sl.GetInstance(item.FilterType);
yield return new Filter(filterInstance, FilterScope.Action);
}
}





Nos recorremos la colección de FilterConfigItems y por cada uno miramos si aplica al controlador pedido y a la acción indicada (los parámetros controllerContext y actionDescriptor nos dan información sobre el controlador y la acción para la cual debemos encontrar los filtros).



Y por cada elemento FilterConfigItem encontrado:




  1. Creamos la instancia del objeto que implementa el filtro. Fijaos que lo hacemos usando MvcServiceLocator.Current: eso permite aplicar inyección de dependencias.


  2. Creamos un objeto Filter (el objeto que espera el framework), lo rellenamos con los datos y lo devolvemos.



Y listos! Nuestro filter provider está listo para usar… Sólo nos queda crearlo, configurarlo y registrarlo en MVC:




FluentFilterProvider ffp = new FluentFilterProvider();
ffp.AddForController<HomeController, MyCustomFilter>().ForAction("Index");
ffp.AddForController<HomeController, MyOtherCustomFilter>();
FilterProviders.Providers.Add(ffp);





Recordad que las clases MyCustomFilter y MyOtherCustomFilter son las clases que implementan los filtros (son las que implementan IActionFilter, IAuthorizationFilter, IResultFilter o IExceptionFilter).



No se que os parece a vosotros, pero a mi me parece una pasada!!! :)



Un saludo!!!!



PD: Como no… eso es un crosspost desde mi blog en geeks.ms! Pásate mejor por allí!

miércoles, 28 de julio de 2010

ASP.NET MVC 3 – Preview 1

Ayer saltaba la noticia en el blog de scottgu: la preview 1 de ASP.NET MVC3 ya está disponible para descargar. En fin, podríamos discutir largo y tendido sobre la política de actualizaciones a lo bestia de las APIs que está realizando microsoft desde hace algún tiempo, pero como cada uno tendría su opinión, mejor vamos a ver las novedades que trae esa preview 1. Antes que nada, podéis instalarla sin miedo: se instala side by side con MVC2 y además los proyectos que ya teníais no se ven afectados.

Una vez instalado MVC3, aparecen tres nuevos tipos de proyectos en VS2010: ASP.NET MVC 3 Web Application (ASPX), ASP.NET MVC 3 Web Application (Razor) y ASP.NET MVC 3 Emtpy Web Application. No hay soporte para VS2008 puesto que MVC3 usa el .NET Framework 4. Vamos a ver las novedades que tiene esta preview1 de MVC3 :)

1. Razor View Engine

El nuevo Razor viene incluído en MVC3. Razor no es nada más que otro ViewEngine para MVC. Ya se ha hablado largo y tendido de Razor porque se incluye también en WebMatrix. Si bien en WebMatrix, Razor venía acompañado del concepto de ASP.NET WebPage, en ASP.NET MVC dicho concepto carece de sentido y Razor es simplemente otro ViewEngine más.

Razor ofrece una sintaxis alternativa a la sintaxis clásica de <% %> tan típica de ASP.NET MVC, pero no ofrece nada nuevo que no ofrezcan el ViewEngine de .aspx u otros como Nhaml o Spark.

Mi “decepción” ha sido que de hecho, tanto si usamos el ViewEngine de .aspx como si usamos Razor, las clases de las vistas derivan de System.Web.Mvc.ViewPage<> (yo tenía la esperanza de que Razor ofreciera un framework mucho más ligero, puesto que ViewPage deriva de System.Web.UI.Page que tiene muchas propiedades y métodos que tienen sentido en WebForms pero sólo añaden ruído en MVC).

P.ej. en Razor para mostrar una lista de elementos (FooItem) que tuviesen dos propiedades llamadas First y Second usaríamos:

@inherits System.Web.Mvc.WebViewPage<IEnumerable<MvcApplication1.Models.FooItem>>

@{
View.Title = "TableView";
LayoutPage = "~/Views/Shared/_Layout.cshtml";
}

<h2>TableView</h2>

<ul>
@foreach (var item in Model)
{
<li>@item.First - @item.Second</li>
}
</ul>





Este es el código entero de la vista: como veis es mucho más compacto que su equivalente en .aspx. ¿Cual preferís? Es una cuestión de gustos, pero según comenta Scott en su post, será posible probar templates de Razor de forma individual sin necesidad de tener un servidor web, lo que ayudará a la generación de pruebas… Por lo que parece esto no está previsto para el ViewEngine de .aspx.



Las vistas en Razor (usando c#) tienen la extensión .cshtml y de momento el soporte en vs2010 de Razor es muy limitado en esta preview1: Ni sintaxis coloreada, ni intellisense… :)



2. Mejor soporte para DI



MVC2 ya tenía un soporte más que decente para dependency injection, pero en MVC3 lo han mejorado: no sólo han simplificado la tarea de usar DI sinó que ahora también se soporta la inyección de dependencias en los filtros.



El soporte para contenedores IoC se basa en la interfaz IServiceLocator y como es uno de los puntos más interesantes a mi parecer, dejadme que me extienda un poco :)



Primero, antes que nada, en la preview1, la interfaz IServiceLocator está definida dentro del propio assembly de System.Web.Mvc.dll, en lugar de usar el del ensamblado Microsoft.Practices.ServiceLocation.dll. Esto genera algunos problemas y es algo que está previsto que cambie en futuras previews.



P.ej. si usamos Unity 2.0, para obtener el IServiceLocator nos basta con hacer:




IUnityContainer iuc = new UnityContainer();
Microsoft.Practices.ServiceLocation.IServiceLocator ul = new UnityServiceLocator(iuc);





La idea es el IServiceLocator que hemos obtenido (ul) lo podamos usar en MVC3, pero por ahora es imposible. La razón es la que comentaba: MVC3 define su propio IServiceLocator en lugar de utilizar el que viene en Microsoft.Practices.ServiceLocation.dll. Así pues, de momento, estamos obligados a implementarnos nuestro “propio” IServiceLocator:




public class MvcUnityServiceLocation : IServiceLocator
{
private readonly IUnityContainer _container;

public MvcUnityServiceLocation(IUnityContainer ctr)
{
_container = ctr;
}


public IEnumerable<object> GetAllInstances(Type serviceType)
{
return _container.ResolveAll(serviceType);
}

public IEnumerable<TService> GetAllInstances<TService>()
{
return _container.ResolveAll<TService>();
}

public object GetInstance(Type serviceType, string key)
{
return _container.Resolve(serviceType, key);
}

public object GetInstance(Type serviceType)
{
return _container.Resolve(serviceType);
}

public TService GetInstance<TService>(string key)
{
return _container.Resolve<TService>(key);
}

public TService GetInstance<TService>()
{
return _container.Resolve<TService>();
}

public object GetService(Type serviceType)
{
return _container.Resolve(serviceType);
}
}





La interfaz que estamos implementando NO ES Microsoft.Practices.IServiceLocator sino System.Web.Mvc.IServiceLocator. Como digo eso es algo que se supone cambiará en futuras previews.



Ahora ya podemos registrar este IServiceLocator, usando la clase MvcServiceLocator (esto se suele hacer en el Application_Start):




IUnityContainer iuc = new UnityContainer();
System.Web.Mvc.IServiceLocator ul = new MvcUnityServiceLocation(iuc);
MvcServiceLocator.SetCurrent(ul);





Bueno… Con eso establecemos cual va a ser el ServiceLocator que usará MVC para instanciar sus objetos. Ahora debemos configurarlo. Una cosa que me he encontrado es que debemos establecer la factoría de controladores explicitamente en el contenedor de IoC:




iuc.RegisterType<IControllerFactory, DefaultControllerFactory>
(new ContainerControlledLifetimeManager());





Aquí estoy diciendo a MVC que use DefaultControllerFactory como factoría de controladores, y la forma de hacerlo es simplemente establecer un mapping entre IControllerFactory y DefaultControllerFactory en mi contenedor IoC.



Y aquí viene la mejora: DefaultControllerFactory ya está preparada para usar el IServiceLocator, por lo que ya tenemos DI en los controladores. Sin hacer nada más (antes uno debía crearse su propia IControllerFactory). Podemos establecer un mapping cualquiera en nuestro contenedor:




iuc.RegisterType<IFoo, Foo>();





Y ya podemos usar IFoo sin ningún problema en nuestros controladores:




public class HomeController : Controller
{
public HomeController(IFoo foo)
{
// ...
}
}





Cada vez que se cree un HomeController se le inyectará el parámetro IFoo.



Antes he comentado que una de las novedades de MVC3 es el soporte de inyección de dependencias para los filtros… Los que conozcais un poco ASP.NET MVC seguramente os estareis preguntando cómo, dado que los filtros son clases que heredan de Attribute y por lo tanto es el propio runtime de .NET quien los crea, sin que el contenedor de IoC pueda intervenir…



Para ayudar a la inyección de dependencias en filtros, en MVC3 se han inventado el concepto del proveedor de filtros, representado por la interfaz IFilterProvider y que es el responsable de obtener instancias de todos los filtros que necesite el framework. Nosotros ahora podemos crear nuestra propia clase que implemente IFilterProvider y que aplique la inyección de dependencias. Veamos primero como está definido IFilterProvider:




public interface IFilterProvider
{
IEnumerable<Filter> GetFilters(ControllerContext controllerContext,
ActionDescriptor actionDescriptor);
}





Un solo método GetFilters que es el encargado de devolver el conjunto de filtros necesarios cada vez. La clase Filter no es el filtro en sí, sinó una clase de metadatos que contiene una referencia al objeto que implementa el filtro (en nuestro caso el atributo), además de información sobre el orden (que ya existía en MVC2) y el àmbito del filtro (p.ej. si es un filtro que se aplica a un controlador, a una acción,…). Los filtros se ejecutan unos antes de otros en función de su ámbito y de su orden.



Bien, si queremos implementar filtros usando atributos podemos hacerlo igual que en MVC2 derivando de FilterAttribute:




public class CustomActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
}
}





Nada nuevo aquí, lo nuevo viene ahora: Podemos crear un IFilterProvider que nos inyecte las dependencias a los filtros. Este IFilterProvider, obviamente, no creará los filtros (puesto que son atributos y los crea el runtime de .NET). Entonces que hace? Pues tres cosas:




  1. Recoge los objetos que implementan los filtros (creados por el runtime)


  2. Por cada objeto le inyecta las dependencias. Para ello necesitamos que el contenedor de DI soporte inyectar dependencias a objetos ya existentes y usar inyección de propiedades.


  3. Finalmente crea el objeto Filter que contendrá el objeto con las dependencias creadas.



Un ejemplo, usando Unity:




public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider
{
private IUnityContainer _container;

public UnityFilterAttributeFilterProvider(IUnityContainer container)
{
_container = container;
}
protected override IEnumerable<FilterAttribute> GetControllerAttributes(
ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
var attributes = base.GetControllerAttributes(controllerContext, actionDescriptor);
foreach (var attribute in attributes)
{
_container.BuildUp(attribute.GetType(), attribute);
}
return attributes;
}

protected override IEnumerable<FilterAttribute> GetActionAttributes(
ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
var attributes = base.GetActionAttributes(controllerContext, actionDescriptor);
foreach (var attribute in attributes)
{
_container.BuildUp(attribute.GetType(), attribute);
}
return attributes;
}
}





Derivamos de FilterAttributeFilterProvider (que implementa IFilterProvider) y usamos Unity para inyectar las dependencias (BuildUp) a los objetos que implementan los filtros.



Y ahora? Pues como siempre: registrar este FilterAttributeProvider en el framework a través del Applicaton_Start de global.asax:




var provider = new UnityFilterAttributeFilterProvider(container);  
FilterProviders.Providers.Add(provider);





Por defecto hay 3 IFilterProviders instalados en el framework (en la colección Providers):





    1. Un filter provider que se encarga de devolver los controladores (sí, los controladores son filtros también (desde siempre)).


    2. Un filter provider que se encarga de devolver los filtros que son atributos


    3. Un filter provider que se encarga de devolver los filtros globales




Dado que nosotros estamos añadiendo otro filter provider que sustituye al que viene por defecto al que se encarga de devolver los filtros que son atributos, no estaría de más eliminar el que viene por defecto antes de registrar el nuestro (aunque funciona si no lo hacemos):




FilterProviders.Providers.Remove(FilterProviders.Providers.FirstOrDefault(x => x is FilterAttributeFilterProvider));





Y listos! Ahora ya tenemos inyección de dependencias en nuestros filtros! Recordad que debemos usar inyección de propiedades, dado que los filtros son creados por el runtime de .NET. Es decir algo como:




public class CustomActionFilterAttribute : ActionFilterAttribute
{
// Esta propiedad la inyecta Unity...
[Dependency]
public IFoo Foo { get; set; }
// ...
}





Que os parece? No es mucho trabajo para el beneficio que obtenemos!



Otra ventaja del uso de filter providers es poder tener filtros que no sean atributos, algo que no estaba permitido en MVC2: cualquier “cosa” que el filter provider devuelva será considerado un filtro para el framework.



3. Otras mejoras menores



Ahora listo brevemente un conjunto de “mejoras menores” que pese a no suponer un avance brutal sirven para simplificarnos el trabajo o mejorar el código:




  1. Soporte para objetos JSON en POST: MVC3 es capaz de tratar datos que están en POST en formato JSON y usarlos cuando hacemos binding del viewmodel. MVC2 no era capaz, aunque no era muy complejo añadir un custom value provider que diera esa capacidad. De hecho en MvcFutures ya estaba y es lógico que haya entrado en esta versión.


  2. Nueva propiedad ViewModel: ViewModel es una propiedad declarada como dynamic que permite usar la antigua ViewData de forma tipada. Es decir en lugar de hacer ViewData[“Foo”] = new Bar(); podemos hacer ViewModel.Foo = new Bar(); y el resultado es equivalente. Esto mejora la legibilidad y facilita refactorings.


  3. Soporte del interfaaz IValidatableObject: Esta interfaz (propia de .NET 4) tiene un sólo método (Validate) que determina si un objeto es “válido”. El model binder por defecto ahora usa ese método si el viewmodel implementa dicha interfaz.


  4. Nuevos ActionResults: Para devolver un 404 (HttpNotFoundResult), o un código específico de HTTP (HttpStatusCodeResult).


  5. Filtros globales: Filtros que se aplican a todos los controladores de nuestra aplicación de forma automática.



Bueno… como podeis ver MVC3 viene con un buen puñado de novedades, muchas de ellas pequeñitas pero sin duda alguna interesantes… larga, larga, larga vida a MVC!!! :)



Referencias



El post de ScottGu explicando MVC3



El post de Brad Wilson explicando la DI en filtros



PD: Esto es un crosspost desde mi blog en geeks.ms