Hace mucho que no escribía nada en el blog y tengo que empezar a coger otra vez la rutina y nada mejor para eso que comenzar con un truquito para utilizar en nuestros desarrollos en ASP.NET MVC.
Como buen truco no me voy a enrollar demasiado en las explicaciones ni teorías y me voy a centrar más en el código para que se pueda utilizar de una manera simple.
El Problema
Imaginemos que tenemos un modelo de datos que utiliza una enumeración.
[sourcecode language=»csharp»]
public class Persona
{
public int Id { get; set; }
public string Nombre { get; set; }
public int Edad { get; set; }
public Genero Genero { get; set; }
}
public enum Genero
{
Hombre,
Mujer,
Geek
}
[/sourcecode]
Una vez tenemos nuestra entidad Genero el controlador y las vistas de forma automática con Visual Studio para no entretenerme mucho con el ejemplo. De esta manera ya lo tengo todo preparado con un solo click.
Nuestra vista de inserción tendría esta pinta:
Como se puede observar la vista se ha creado perfectamente para añadir nuevas personas, pero no se a mapeado correctamente la enumeración para seleccionar el sexo de la persona.
Si lo intentáramos bindar directamente con el modelo tendríamos igualmente el problema porque no sabe mapear la enumeración directamente.
Solución Rápida
A los elementos html de MVC se le pueden pasar directamente un lista para mostrar los datos y gracias a eso podemos forzar el mapeo de una forma muy fácil.
[sourcecode language=»html»]
<div class="editor-field">
@Html.DropDownListFor(model => model.Genero,
new SelectList(Enum.GetValues(typeof(Genero))))</div>
[/sourcecode]
En este truco lo único que hacemos es pasar al control la lista de elementos que acepta haciendo un cast de la enumeración y ya tenemos la vista funcionando perfectamente.
Solución Elegante
Si en nuestra aplicación utilizamos muchas entidades con enumeraciones nos interesaría reutilizar el código y no tener que hacer la conversión cada vez. Para eso podemos extender el helper del DropDownListFor para tener nuestro propio helper que acepte enumeraciones.
[sourcecode language=»csharp»]
public static class HtmlExtensions
{
public static MvcHtmlString DropDownListForEnum<TModel, TEnum>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TEnum>> expression)
{
var list = new SelectList(Enum.GetValues(typeof (TEnum))).ToList();
var selectList = list.ToList();
return htmlHelper.DropDownListFor(expression, selectList);
}
}
[/sourcecode]
Con nuestro nuevo helper ahora podemos utilizar las enumeraciones del modelo de una forma más natural y práctica.
[sourcecode language=»html»]
<div class="editor-field">
@Html.DropDownListForEnum(model => model.Genero )</div>
[/sourcecode]
Y la aplicación funciona perfectamente con nuestras enumeraciones.
El toque final
Ya tenemos nuestra extensión del control, pero que pasa si queremos añadirle atributos html como el control original, ahora mismo tal como está no lo permite. Pues lo único que tenemos que hacer es sobrecargar el nuevo control para que acepte este nuevo parámetro y ya lo tendremos solucionado.
[sourcecode language=»csharp»]
public static class HtmlExtensions
{
public static MvcHtmlString DropDownListForEnum<TModel, TEnum>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TEnum>> expression,
Object htmlAttributes)
{
var list = new SelectList(Enum.GetValues(typeof (TEnum))).ToList();
var selectList = list.ToList();
return htmlHelper.DropDownListFor(expression, selectList, htmlAttributes);
}
public static MvcHtmlString DropDownListForEnum<TModel, TEnum>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TEnum>> expression)
{
return htmlHelper.DropDownListForEnum(expression, null );
}
}
[/sourcecode]
Ahora podemos especificar atributos Html para el renderizado del control.
[sourcecode language=»html»]
<div class="editor-field">
@Html.DropDownListForEnum(model => model.Genero,
new {@class="dropdown" } )</div>
[/sourcecode]
Y la personalización del control se mostraría con el estilo especificado en el helper.
Espero que este truco os sea útil para vuestros desarrollos y si queréis profundizar más con las enumeraciones en MVC podéis ver la entrada de Eduard Tomas en su blog.
Nuevo artículo en el blog logro desbloqueado 😉