Gerardo Contijoch

Experiencias del día a día trabajando con .NET – ASP.NET, C#, ASP.NET MVC y demas…

Archive for the ‘ASP.NET MVC’ Category

Un CheckBoxList que funciona en ASP.NET MVC

Posted by Gerardo Contijoch en julio 4, 2009

Si buscamos en internet ‘CheckBoxList ASP.NET MVC’ encontraremos infinidad de páginas con quejas de la desaparición del método de extensión CheckBoxList() de la clase HtmlHelper en la Preview 5 de ASP.NET MVC (antes de la versión oficial). Este es un problema de aparente fácil resolución ya que el método CheckBox() sigue estando presente, por lo que una lista de CheckBoxes podría crearse con un código similar al siguiente:

   1: <% for (int i = 0; i < 4; i++) {%>
   2:   <%= Html.CheckBox("checks", (object)new { value = "val" + i.ToString() })%><%= "Check " + i.ToString() %><br/>
   3: <%}%>

Sin embargo, rápidamente nos vamos a encontrar con dos problemas. El primero de ellos se hace presente dentro del código de la acción que se ejecuta al postear el form.

Dada la siguiente vista:

   1: <% using (Html.BeginForm("Index1", "Home", FormMethod.Post)) { %>
   2:     <% for (int i = 0; i < 4; i++) {%>
   3:         <%= Html.CheckBox("checks1", (object)new { value = "val" + i.ToString() })%><%= "Check " + i.ToString() %><br/>
   4:     <%}%>
   5:     <input type="submit" value="Post!" />
   6: <%}%>

veamos como recibimos los valores de los CheckBoxes si tildamos sólo los dos primeros CheckBoxes (los asociados a los valores ‘val0’ y ‘val1’):

aspnetmvc-checkboxes-valoresChecks1

Como se puede apreciar, lo que recibimos es un array de valores un tanto desconcertante. Esto se debe a la manera en que postea el valor de los CheckBoxes.

Posteo de Checkboxes

Un CheckBox no es más que un input de tipo checkbox en una página, el cual puede tener o no un valor asociado. A diferencia de como funciona un input de tipo text (un TextBox), el valor del checkbox sólo se postea si el mismo esta tildado. Esto significa que si en un form HTML no tildamos un CheckBox, su valor no será enviado al servidor, lo cual puede traer muchos problemas en ASP.NET MVC si nuestra acción (la asociada al form que posteamos) tiene que recibir como parámetro el valor del CheckBox, ya que la llamada fallará cuando este no este tildado y el DefaultModelBinder no pueda asignarle un valor al parámetro asociado al mismo (debido a que no se posteó).

Es por este problema que el método de extensión CheckBox renderiza dos inputs en vez de uno solo. El primer input es el propio CheckBox (un imput de tipo ‘checkbox’), y el segundo es un input de tipo hidden llamado igual, pero cuyo valor esta hardcodeado a ‘false’. Es decir, dado el siguiente código:

   1: <%= Html.CheckBox("checkbox") %>"Check"

se renderiza lo siguiente en la página:

   1: <input id="checkbox" type="checkbox" value="true" name="checkbox"/>
   2: <input type="hidden" value="false" name="checkbox"/>
   3: Check
   4: <br/>

Así, si posteamos el form sin tildar el CheckBox, se postea el valor del input oculto, es decir, para la variable del post ‘checkbox’ se asigna el valor ‘false’ (que en el servidor es transformado en el booleano False). En cambio, si tildamos el CheckBox, se postea el valor ‘true, false’ (uno por cada input). Este valor es procesado por el DefaultModelBinder y lo interpreta como el booleano True.

Posteo de más de un CheckBox

Hay que reconocer que es un método bastante ingenioso de resolver el problema, pero lamentablemente está pensado para funcionar sólo con un único CheckBox. Volviendo al ejemplo que presenté al comienzo de este post, se puede ver ahora que el array que recibimos en nuestra acción esta conformado por los valores asociados a cada uno de los CheckBoxes renderizados, esto es, se posteo ‘val0, false’ para el primer CheckBox, ‘val1, false’ para el segundo, ‘false’ para el tercero, y ‘false’ para el cuarto (recordemos que los dos últimos CheckBoxes no fueron tildados). Esta forma de recibir los parámetro puede ser bastante problemática. Por un lado, no podemos procesar los valores con un foreach ya que no todos los valores nos interesan, sólo aquellos que son distintos a ‘false’ nos resultan útiles. Uno podría discriminar estos valores para recuperar sólo el set que nos interesa, pero esto es posible únicamente si no posteamos valores booleanos ya que si efectivamente queremos un valor ‘false’ cuando no tildamos un CheckBox, no vamos a poder ubicarlo fácilmente dentro del array. Es verdad que uno puede imaginarse una lógica un tanto compleja en donde si se encuentra un valor ‘true’, entonces ignora el siguiente valor (que debería ser ‘false’), pero esto tiene una utilidad limitada, ya que muy posiblemente nos topemos con el segundo de los problemas que mencioné anteriormente.

Este segundo problema es similar al del posteo de los valores, pero se presenta a la hora de mostrarlos a los valores. Cuando posteamos un form en ASP.NET MVC los parámetros de las acciones se cargan en el ModelState, lo cual nos permite, al momento de renderizar la vista inicializar los valores de los controles con los valores posteados para que los mismos no aparezcan vacíos (recordemos que la web es stateless y luego de un post las páginas se vuelven a cargar desde cero). El modo de hacerlo es matcheando los nombres de los controles (atributo name) con las entradas del ModelState. Así, si tenemos un TextBox llamado ‘txtNombre’, ASP.NET MVC va a crear una entrada dentro del ModelState con el nombre ‘txtNombre’ asociado al valor posteado en el TextBox. Al momento de renderizar la página se consulta el ModelState y se cargan los valores posteados con anterioridad. Particularmente en nuestro caso, lo que se carga en el ModelState es un arrays de valores, el cual esta asociado a todos los CheckBoxes en el form. Y eso es un problema ya el método CheckBox() no esta preparado para procesar un array de valores, sino un único valor que determina si un CheckBox esta o no tildado (ese código puede verse claramente cerca de la línea 153 de la clase InputExtensions en el código fuente de ASP.NET MVC). Como consecuencia de esto, si tenemos más de un CheckBox con el mismo nombre en el form, los mismos no van a recuperar su estado anterior.

Un CheckBoxList que funciona

Dado ese problema, decidí crear un nuevo CheckBoxList personalizado (hay un par de implementaciones dando vueltas, pero no encontré ninguna que resolviera el segundo problema).

El código es bastante sencillo y esta ‘inspirado’ en el código del CheckBox original de ASP.NET MVC.

   1: public static partial class HtmlHelperExtensions {
   2:
   3:     public static string CheckBoxList(this HtmlHelper htmlHelper, string name, IEnumerable<string> values, object htmlAttributes) {
   4:         return CheckBoxList(htmlHelper, name, values, values, htmlAttributes);
   5:     }
   6:
   7:     public static string CheckBoxList(this HtmlHelper htmlHelper, string name, IEnumerable<string> values, IEnumerable<string> labels, object htmlAttributes) {
   8:         // No creamos ningun CheckBox si no hay valores
   9:         if (values == null) {
  10:             return "";
  11:         }
  12:
  13:         if (labels == null) {
  14:             labels = new List<string>();
  15:         }
  16:
  17:         RouteValueDictionary attributes = htmlAttributes == null ? new RouteValueDictionary() : new RouteValueDictionary(htmlAttributes);
  18:         attributes.Remove("checked");
  19:
  20:         StringBuilder sb = new StringBuilder();
  21:
  22:         string[] modelValues = new string[] { };
  23:
  24:         ModelState modelState;
  25:         if (htmlHelper.ViewData.ModelState.TryGetValue(name, out modelState)) {
  26:             modelValues = ((string[])modelState.Value.RawValue);
  27:         }
  28:
  29:         // Por cada valor pasado generamos un CheckBox
  30:
  31:         IEnumerator<string> labelEnumerator = labels.GetEnumerator();
  32:         foreach (string s in values) {
  33:             // Si el array contiene el valor correspondiente a este checkbox, entonces fue chequeado
  34:             bool isChecked = modelValues.Contains(s);
  35:             sb.Append(CrearCheckBox(name, s, isChecked, attributes));
  36:
  37:             labelEnumerator.MoveNext();
  38:             if (labelEnumerator.Current != null) {
  39:                 sb.AppendLine(labelEnumerator.Current);
  40:             }
  41:         }
  42:
  43:         // Creamos el div contenedor
  44:         TagBuilder divTag = new TagBuilder("div");
  45:         divTag.InnerHtml = sb.ToString();
  46:
  47:         // No nos olvidemos de indicar si hay un error en alguno de los checks
  48:         if (modelState != null && modelState.Errors.Count > 0) {
  49:             divTag.AddCssClass(HtmlHelper.ValidationInputCssClassName);
  50:         }
  51:
  52:         return divTag.ToString(TagRenderMode.Normal);
  53:     }
  54:
  55:     private static string CrearCheckBox(string name, string value, bool isChecked, IDictionary<string, object> htmlAttributes) {
  56:         TagBuilder tagBuilder = new TagBuilder("input");
  57:         tagBuilder.MergeAttributes(htmlAttributes);
  58:         tagBuilder.MergeAttribute("type", "checkbox");
  59:         tagBuilder.MergeAttribute("name", name, true);
  60:
  61:         tagBuilder.GenerateId(name);
  62:
  63:         if (isChecked) {
  64:             tagBuilder.MergeAttribute("checked", "checked");
  65:         }
  66:
  67:         if (value != null) {
  68:             tagBuilder.MergeAttribute("value", value, true);
  69:         }
  70:
  71:         return tagBuilder.ToString(TagRenderMode.SelfClosing);
  72:     }
  73: }

Su uso es muy sencillo:

   1: <%
   2:    List<string> values = new List<string>() { "val0", "val1", "val2", "val3", "val4" };
   3:    List<string> labels = new List<string>() { "Check 0", "Check 1", "Check 2", "Check 3", "Check 4" };
   4: %>
   5: <%= Html.CheckBoxList("checks3", values, labels, null) %>

Los valores en la acción son recibidos así:

aspnetmvc-checkboxes-valoresChecks2

El código podría mejorarse un poco más agregando la posibilidad de aplicarles estilos al div contenedor de los CheckBoxes, usar labels reales en vez de solo texto, agregar sobrecargas a los métodos, etc., pero preferí dejarlo así porque era más sencillo. Es preciso aclarar que este CheckBoxList, al igual que la primer alternativa que presenté, no va a funcionar bien con valores booleanos ya que la idea es que los valores asociados a cada uno de los CheckBoxes sean únicos.

Si encuentran algún bug o tienen algo que aportar, no duden en comentarlo.

¡Nos vemos en el próximo post!

Publicado originalmente en https://gerardocontijoch.wordpress.com.

Posted in ASP.NET MVC, Desarrollo Web | Etiquetado: , , , | 3 Comments »

Inicialización del ModelState en ASP.NET MVC

Posted by Gerardo Contijoch en junio 21, 2009

Hoy mientras trabajaba en un site ASP.NET MVC aprendí una lección que espero no olvidar jamás (su olvido me podría traer muchos dolores de cabeza).

El problema se presentó cuando uno de los campos del form con el que estaba trabajando no se actualizaba luego de un postback. El form no tenia nada de especial, sólo un par de campos, y su posteo provocaba la ejecución de una acción que tampoco hacia nada muy loco. Lo único destacable era que el parámetro con problemas era cargado con un ModelBinder personalizado, pero el mismo funcionaba bien y lo inicializaba correctamente al valor. Lo primero que hice fue verificar que las variables del post lleguen correctamente al server. También verifiqué que no haya ningún código javascript interfiriendo con el llenado de campos. Lo que más me desconcertó fue que dentro de la acción, el parámetro cuyo valor tenia problemas estaba correctamente inicializado, cosa que no esperaba (lo que me llevó a pensar que no había un error en el ModelBinder). Sin embargo había un detalle que pasé de largo: entre los valores del ModelState del request no se encontraba el parámetro con problemas. Fue cuando descubrí eso que supe donde estaba el problema. Un poco más de investigación me confirmó las sospechas. Pero antes de explicarles el problema, veamos el código del ModelBinder:

   1: public class TipoDeOperacionModelBinder : IModelBinder {
   2:     #region IModelBinder Members
   3:
   4:     public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
   5:
   6:         if (bindingContext == null) {
   7:             throw new ArgumentNullException("bindingContext");
   8:         }
   9:
  10:         ValueProviderResult val;
  11:         if (!bindingContext.ValueProvider.TryGetValue(bindingContext.ModelName, out val)) {
  12:             // Si no encontramos el valor, devolvemos null y ASP.NET MVC se encarga de provocar la excepción necesaria
  13:             return null;
  14:         }
  15:
  16:         int realVal = (int)val.ConvertTo(typeof(int));
  17:         return (TipoDeOperacion)realVal;
  18:     }
  19:
  20:     #endregion
  21: }

Este ModelBinder simplemente toma un valor (indicado por bindingContext.ModelName) y lo transforma en un Enum de tipo TipoDeOperacion. Cabe aclarar que este ModelBinder esta registrado para el tipo TipoDeOperacion, por lo que el propio framework es el encargado de hacer uso del mismo cuando necesite hacer el binding de un parámetro de tipo TipoDeOperacion.

Como dije antes, el parámetro en cuestión se inicializaba correctamente, lo que confirmaba que las variables del post llegaban sin problemas. El problema estaba en que no se encontraba dentro del ModelState y eso se debe sencillamente a que en ningún lugar del código del ModelBinder lo estoy agregando. Resulta que el ModelBinder no solo es responsable de cargar los parámetros de las acciones y actualizar el modelo con el que estamos trabajando, sino que ¡también debe inicializar el ModelState! El resto de los parámetros de la acción no tenían problemas ya que eran procesados por la clase DefaultModelBinder, la cual se encarga de todo. Todo se resolvió cuando agregué el siguiente código en la línea 15:

bindingContext.ModelState.SetModelValue(bindingContext.ModelName, val);

Parece una pavada de detalle, pero esa sola línea de código me hizo perder varias horas de trabajo por no saber que el ModelState era cargado por los ModelBinders. Esto demuestra la importancia de entender bien las herramientas y frameworks con los que uno trabaja. ASP.NET MVC nos provee de montones de puntos de extensión, pero de nada sirve si no los sabemos aprovechar correctamente.

¡Nos vemos en el próximo post!

Publicado originalmente en https://gerardocontijoch.wordpress.com.

Posted in ASP.NET MVC | Etiquetado: , , | Leave a Comment »

Restaurar ViewData luego de hacer un Redirect en ASP.NET MVC

Posted by Gerardo Contijoch en mayo 9, 2009

Una de las consecuencias de hacer un redirect desde una acción en ASP.NET MVC es que se pierde toda la información que tenemos guardada en el ViewData así como también en el ModelState. Esto se debe a que esos dos diccionario se utilizan para pasarle información desde los controladores a las vistas y si hacemos un redirect, lógicamente no vamos a estar devolviendo ninguna vista, por lo que sus valores son descartados cuando comienza la ejecución de la acción a la que redirigimos. Para evitar esto, se pueden guardar estos valores en la propiedad TempData, la cual es persistida entre requests. Como esto se puede volver un poco tedioso y repetitivo (por no decir poco elegante), decidí crear un par de ActionFilters que se encarguen de persistir valores del ViewData y de recuperarlos cuando sea necesario. El siguiente código esta basado en este post, el cual contiene la solución para persistir el ModelState.

Les presento un ejemplo de como se utilizan estos atributos y a continuación el código de los mismos.

   1: public class TestController : Controller {
   2:
   3:     [ExportarViewDataItem("Nombre")]
   4:     public RedirectToRouteResult AccionConRedirect() {
   5:         // ...
   6:         ViewData["Nombre"] = "Gerardo";
   7:         // ...
   8:         return RedirectToAction("Index");
   9:     }
  10:
  11:     [ImportarViewDataItem("Nombre")]
  12:     public ViewResult Index() {
  13:         string nombre = ViewData["nombre"].ToString();
  14:         // ...
  15:         return View();
  16:     }
  17:
  18: }

La implementación actual de los atributos requiere que se especifique un key a exportar e importar, pero los atributos son muy fácilmente modificables para que exporte e importe el ViewData completo sin necesidad de especificar cada uno de los keys.

Aca esta el código:

   1: /// <summary>
   2: /// Clase base para los atributos que exportan e importan valores de ViewData.
   3: /// </summary>
   4: public abstract class ViewDataTransferAttribute : ActionFilterAttribute {
   5:
   6:     public string Key { get; set; }
   7:
   8:     protected ViewDataTransferAttribute(string key) {
   9:         if (string.IsNullOrEmpty(key)) {
  10:             throw new ArgumentException("El parámetro key no puede ser null o vacío.", "key");
  11:         }
  12:
  13:         Key = key;
  14:     }
  15:
  16:     /// <summary>
  17:     /// Key interna para referenciar al valor guardado.
  18:     /// </summary>
  19:     /// <remarks>Se usa una key intena para asegurarnos de que no hay conflictos de keys con valores ya existentes.</remarks>
  20:     protected string InternalKey { get { return "_viewDataItem_" + Key; } }
  21: }
  22:
  23: [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
  24: public class ExportarViewDataItemAttribute : ViewDataTransferAttribute {
  25:
  26:     public ExportarViewDataItemAttribute(string key) : base(key){}
  27:
  28:     public override void OnActionExecuted(ActionExecutedContext filterContext) {
  29:
  30:         // Si no hacemos un redirect, entonces no tiene sentido respaldar los valores
  31:         if (filterContext.Result is RedirectResult || filterContext.Result is RedirectToRouteResult) {
  32:
  33:             var valor = filterContext.Controller.ViewData[Key];
  34:
  35:             if (valor != null) {
  36:                 var tempData = filterContext.Controller.TempData;
  37:                 if (tempData.ContainsKey(InternalKey)) {
  38:                     tempData.Remove(InternalKey);
  39:                 }
  40:                 tempData.Add(InternalKey, valor);
  41:             }
  42:         }
  43:
  44:         base.OnActionExecuted(filterContext);
  45:     }
  46: }
  47:
  48: [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
  49: public class ImportarViewDataItemAttribute : ViewDataTransferAttribute {
  50:
  51:     public ImportarViewDataItemAttribute(string key) : base(key) { }
  52:
  53:     public override void OnActionExecuting(ActionExecutingContext filterContext) {
  54:
  55:         var valor = filterContext.Controller.TempData[InternalKey];
  56:
  57:         if (valor != null) {
  58:             var viewData = filterContext.Controller.ViewData;
  59:             if (viewData.ContainsKey(Key)) {
  60:                 viewData.Remove(Key);
  61:             }
  62:             viewData.Add(Key, valor);
  63:             // Limpiamos TempData
  64:             filterContext.Controller.TempData.Remove(InternalKey);
  65:         }
  66:
  67:         base.OnActionExecuting(filterContext);
  68:     }
  69: }

Se puede bajar el proyecto con los atributos y los tests asociados desde aquí.

¡Nos vemos en el próximo post!

Publicado originalmente en https://gerardocontijoch.wordpress.com.

Posted in ASP.NET MVC, Desarrollo Web | Etiquetado: , , , , | Leave a Comment »

Aprender ASP.NET MVC

Posted by Gerardo Contijoch en abril 25, 2009

Hace poco surgió en la blogósfera, una vez mas, la discusión sobre si ASP.NET MVC es mejor o peor que ASP.NET WebForms y si vale la pena aprender a usarlo. No es la primera vez que hay una discusión de este tipo y no será la última.

Esta vez quisiera aportar mi granito de arena a la discusión y para ello les voy a contar una breve historia personal.

Comencé a trabajar con WebForms hace unos 6 años. Esa fue mi primer experiencia Web, nunca antes había trabajado mas que con HTML puro. Como la mayoría en ese momento (imagino yo), empecé con los tutoriales de Microsoft y con algún Starter Kit. Luego llegó el programa Desarrollador 5 Estrellas de Microsoft, al cual seguí. Y no olvidemos los blogs y sites como Code Project o 4 Guys From Rolla, de los cuales uno puede aprender muchísimo. Sin embargo me resulto muy complicado comenzar a trabajar. Y no era que me faltara dominio del manejo de objetos o falta de habilidades para entender conceptos de programación, ya que en cualquier otro tipo de proyectos no tenía ningún problema. Llegó el punto en que llegué a detestar el desarrollo web. No quería saber nada de la Web, ¡no entendía como había gente que le gustara! Era terriblemente complicado para mi trabajar con conceptos como controles de usuario. Entendía que de alguna manera un objeto ‘TextBox’ terminaba siendo un ‘<input>’ del lado del cliente. Entendía que el ViewState ayudaba a que no se pierdan los valores de los controles. Entendía la diferencia entre procesamiento del lado del cliente y procesamiento del lado del servidor. Sin embargo no entendía como sucedía todo eso y ese era mi problema (y es el de muchos otros). ASP.NET hace un excelente trabajo ocultándole al usuario la verdadera naturaleza de la web y del desarrollo web. ¡No fue hasta un par de años después de comenzar a trabajar con ASP.NET que entendí que era POST y GET! Es increíble, pero sí, hice desarrollo web sin saber lo que era POST y GET (entre muchas otras cosas, por supuesto). Es como conducir un tren sin saber que tiene que ir sobre rieles, el tren va derecho sin que uno haga nada, pero uno no sabe porque es así.

Afortunadamente me topé con el blog de InfinitiesLoop y su famosísimo post Truly Understanding ViewState. Créanme que no estoy exagerando cuando les digo que ese post cambio para siempre mi forma de ver ASP.NET. Fue un click, un instante en que cambió todo. Desde ese momento dejé creer en la magia de ASP.NET y comencé a buscar el porqué y el cómo de todo lo que sucedía en una página. Y fue durante esa búsqueda en la que aprendí que era realmente el desarrollo web. No podía creer todas las ‘mentiras’ (por llamarlas de alguna manera) que había aprendido de ASP.NET. Ojo, ASP.NET no es que sea malo por eso, pero el camino natural de aprendizaje de ASP.NET lo lleva a uno a pensar en terminos de ‘Textboxes’, ‘UpdatePanels’ y propiedades que ‘mágicamente’ persisten en el tiempo en un entorno ‘stateless’ (sin estado) en vez de en posts, forms y requests asincrónicos, que es lo que realmente uno necesita dominar.

¿A qué viene todo esto? Sigan leyendo.

Yo comencé a jugar con ASP.NET MVC desde la Preview 3 (ya hace casi un año) y desde el primer momento me atrapó. No había controles de servidor que me abstraigan de cosas que en realidad no debería abstraerme. No había ViewState, ya no era necesario preocuparme por que guardaba y que no guardaba ahí ni por el tamaño de este. No había más misteriosos scritps que eran inyectados en las páginas sin que lo sepamos. No tenia que preocuparme por decidir si realmente me convenía manejar un evento de un campo de texto en el cliente o del lado del servidor. No existía mas el ciclo de vida de las paginas y sus controles (vean la comparación). Era un enfoque totalmente diferente, en donde el desarrollo web solo se limita a las vistas.

Como podrán notar, tengo preferencia por ASP.NET MVC frente al desarrollo clásico con WebForms, pero eso no significa que no siga trabajando con ellos. Lo sigo haciendo, pero ahora, a diferencia de hace algunos años, se lo que hago, se los pros y los contras de usar o no usar un WebControl, se cuando conviene escribir un HttpHandler en vez de una página y se que consecuencias puede traerme el deshabilitar el ViewState para una página. Ahora tengo más control sobre lo que hago y cómo lo hago porque lo entiendo.

De todos modos prefiero ASP.NET MVC por ser mucho mas sencillo de trabajar. Es más modular (puedo hacer un site entero sin haber escrito una línea de código de lógica de negocios o haber creado las tablas en una base de datos), más fácil de testear (la forma en que esta diseñado lo permiten), es totalmente extensible o personalizable (se puede inyectar código en casi cualquier parte de la cadena de procesamiento de un request), los sites tienden a ser mas livianos (no hay mas ViewState o scripts inyectados por defecto, ni hay que renderizar nada, todo es puro html), etc. Parte de esto se debe a la aplicación del patrón MVC, y parte a la forma en que fue implementado por Microsoft.

¿Porqué aprender ASP.NET MVC?

Rob Connery menciona algunas cuestiones por las que él considera que uno debería aprender ASP.NET MVC y no puedo estar más de acuerdo con él. Sobre todo por la anteúltima: Aprender nuevos conceptos. Usando este framework uno puede aprender nuevos patrones y principios de diseño (Model-View-Controller, Repository, Dependency Injection, Inversion of control, Factory, Template, etc ), mejorar nuestras habilidades con javascript (lo más probable es que querramos darle cierta interactividad a nuestro site, y para eso usamos javascript), conocer nuevas herramientas o librerías (para javascript lo más común es usar jQuery o prototype, para IoC podemos usar un framework como Castle MicroKernel, para el acceso a datos es común ver implementaciones hechas con Linq, NHibernate y Entity Framework), y por sobre todas las cosas, ser mejores desarrolladores y estar mejor preparados para el futuro al conocer las distintas opciones que tenemos para trabajar.

[Update: Aclaro que con WebForms uno también puede aprender patrones, usar javascript, librerías, etc, pero como mencioné anteriormente, el camino natural de aprendizaje con WebForms no hace evidente todas esas cuestiones, mientras que con ASP.NET MVC, sí.]

Con todo esto no quiero decir que ASP.NET MVC les va a solucionar todos los problemas, y que deban abandonar los WebForms, para nada, pero creo que puede llegar a ser un aporte muy interesante en la carrera de un desarrollador web.

Recursos

Hay muchos recursos para aprender ASP.NET MVC, pero la mayoría esta en inglés. Entre los más recomendables se encuentran:

[Update: Se agregaron links a blogs en español sobre ASP.NET MVC.]

De ahora en adelante voy a tratar de postear más contenido relacionado a ASP.NET MVC ya que es un tema que me interesa muchísimo y hay muy poco material en español. Si les interesa y tienen alguna sugerencia o duda sobre el tema, no duden en hacerla.

¡Nos vemos en el próximo post

Publicado originalmente en https://gerardocontijoch.wordpress.com.

Posted in ASP.NET, ASP.NET MVC, Desarrollo Web | 4 Comments »