Una sinfonía en C#

Un pequeño aporte a la comunidad de habla hispana.

ASP.NET MVC Series–ActionResults

Todos los controladores en ASP.NET MVC tiene como tipo de resultado un ActionResult (o casi) la pregunta es por qué?

Los ActionResult con objetos que encapsulan respuestas HTTP

Tal cual, ActionResult no es más que una abstracción para respuestas HTTP, entonces podemos decir que todos los controladores retornan respuestas HTTP cosa que es muy lógica en un framework Web.

Diferentes tipos de ActionResults

Hay muchos, y dependiendo de la versión de ASP.NET MVC cambian, así que vamos a enumerar los más comunes:

ViewResult: éste es bien clásico, representa una vista, es decir, un HTML, en principio lo que hace es localizar una vista dada (si no indicamos cuál busca una vista con el mismo nombre de la acción) le pasa el modelo, la procesa y la devuelve al cliente como HTML, por ejemplo:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }

Y la respuesta es un HTTP 200 en el cual el Content-type es text/html

image

En este caso se buscará la vista llamada “index” dentro de la carpeta Views-home por ya que el nombre del controlador es “HomeController” (convención)

Nada impide que especifiquemos otra vista pasando el nombre como parámetro.

RedirectResult: éste es una respuesta HTTP del tipo 302 que indica una redirección, sería así

public ActionResult Ir()
{
    return Redirect("http://www.otro.com");
}

Si miramos el detalle de la respuesta HTTP vemos que no es más que una redirección

image

RedirectToAction: Es una redirección también, igual a la anterior nada más que sólo debemos indicar el nombre de la acción dentro del un controlador a la cual queremos redireccionar en lugar de una URL literal.

ContentResult: Éste es más interesante, nos permite devolver un contenido cualquiera, por ejemplo un archivo de texto, por supuesto es un HTTP 200 y tenemos que indicar el contenido y además el Content-type para que el navegador sepa interpretarlo

public ActionResult Contenido()
{
    return Content("hola mundo", "text/plain");
}

y la respuesta sería:

image

HTTPNotFound: Como su nombre indica es un código 404 HTTP para indicar que un contenido no existe

public ActionResult NoExiste()
{
    return HttpNotFound();
}

image

Generando ActionResults a mano

Estos ActionResults los tenemos como métodos porque existen en la clase base Controller de la cual hereda nuestro controlador, nada nos impide crear los nuestros, por ejemplo si quisiéramos un tipo de resultado HTTP 415 (Unsupported Media Type) podríamos hacerlo nosotros usando la clase ActionResult como clase base y configurando algunas propiedades, por ejemplo:

    public class HomeController : Controller
    {
        public ActionResult NoSoportado()
        {
            return new UnsoportedMediaTypeResult();
        }
    }

    public class UnsoportedMediaTypeResult : ActionResult
    {
        public override void ExecuteResult(ControllerContext context)
        {
            context.HttpContext.Response.StatusCode = 415;
            context.HttpContext.Response.StatusDescription = "Unsoported media type";
        }
    }

Simplemente heredamos de ActionResult y sobre-escribimos el método ExecuteResult, dentro del mismo recibimos como parámetro el context y dentro del él el HttpContext, es simple forzar valores en el objeto Response para lograr lo que buscamos.

image

Excelente, entonces, los ActionResult no son más que representaciones de respuestas HTTP. Existen muchos tipos predefinidos y muchos detalles más que veremos más adelante.

Hasta la próxima.

jQuery, Reemplazar “live” por “on”

 

Como sabemos nuestra querida librería jQuery sigue avanzando en versiones y las últimas actualizaciones han traído algunos cambios, algunos de ellos son más bien internos, transparentes para nosotros, pero otros no tanto

jQuery.live eventos a futuro

Una de las características que en algún momentos nos encontramos con la necesidad de usar es la posibilidad de asociar eventos a algún elemento, esto es bien común, sin embargo a veces ese elemento se genera dinámicamente (por ejemplo una listado que se actualiza) entonces, no existe cuando ejecutamos el código que asocia el evento.

http://007fanart.files.wordpress.com/2010/06/lald3.jpg

Asociar eventos a objetos que existen y existirán

Una forma de lograr esto fácil con jQuery es usar

$("a.boton").live("click", function(){
	alert("me apretaste!!!");
});

Es decir, utilizar la función live como usaríamos la función bind, con la diferencia que live se queda “mirando” los elementos que alcanza un selector después de su ejecución, entonces el evento será asociado a los elementos actuales (los haya o no) y a todos los futuros, para “apagar” esta funcionalidad basta con usar die.

$("a.boton").die("click");

Deprecado

A partir de jQuery 1.9 live y die ha sido deprecados y en su lugar hay que usar la función on y off, que de paso son más performantes, de la siguiente manera:

$("a").on("click",".boton", function(){
	alert("me apretaste!!!");
});
$("a").off("click",".boton");

Un detalle no menos es el segundo parámetro, en este caso selecciono todos los elementos del tipo a y luego hago un filtro por clase boton, podría no utilizar el filtro, pero no obtendría el efecto de live sino que sería un simple click común y corriente.

Entonces ya lo saben, a partir a ahora a usar on y off en nuestros eventos, nos leemos.

ASP.NET MVC Series–Hola MVC

Vamos a poner manos en el código rápido para ir viendo algunos conceptos en la práctica.

Primer ejemplo

Abrimos el Visual Studio 2012 Express for Web, creamos un nuevo proyecto y nos encontramos con las siguientes opciones:

image

Dentro de las opciones vemos un par de ASP.NET Web y un par de ASP.NET MVC, las que nos interesan a nosotros son las ASP.NET MVC, las otras son del tipo Web Forms.

Si bien tenemos las opciones ASP.NET MVC 3 y 4, vamos a empezar con la versión 3 ya que a mi entender la versión 4 tiene algunos cambios fuertes en comparación con la 2 y la 3 y va a ser más sencillo empezar por la 3 para después agregar los conceptos más nuevos.

Entonces creamos un proyecto ASP.NET MVC 3 y le ponemos un nombre, en un ataque se sagacidad y astucia se me ocurre ponerle “hola mundo”

image

La siguiente ventana nos da más opciones, en este caso vamos a elegir “Empty” y en la opción “View engine” dejamos Razor

Estructura del proyecto

Una vez creado el proyecto vemos unas cuantas particularidades en lo que se refiere a la organización:

image

Por defecto se crean varias carpetas:

  • Content
  • Controllers
  • Models
  • Scripts
  • Views

y además vemos algunos archivos

  • Global.asax
  • Web.config

(de momento ignoremos el resto)

Convención sobre configuración

Ya dijimos que una de las características del ASP.NET MVC es la utilización de convención sobre configuración, es decir, en lugar de tener que definir dónde se buscan ciertos recursos por convención se buscan en tal lugar, vamos a profundizar enseguida.

Cómo arranca el proyecto ASP.NET MVC?

Bien, ni lerdos ni perezosos vamos a presionar F5 para ejecutar el proyecto, luego de unos momentos se abre nuestro navegador por defecto y vemos lo siguiente:

image

Nada. Se rompió, y es lógico, dijimos que es el controlador quien recibe las peticiones del usuario y no hemos creado ninguno, por lo tanto no hay quien reciba la petición de la URL http://localhost:62078 (puede cambiar)

La pregunta es “cómo agregamos un controlador” y más importante aún “dónde lo agregamos”, bien, simplemente hacemos botón derecho sobre la carpeta “Controllers” (esta es una de las convenciones, todos los controladores deben estar ahí) y agregamos uno nuevo, vamos a ponerle “HomeController” como nombre y vamos a explicar por qué.

image

El nombre que pusimos tampoco es casual y sigue una convención, todos los controladores se llaman AlgoController (donde “Algo” es un nombre cualquiera)

image

El código generado tiene un método que se llama Index, esto es otra convención y funciona del siguiente modo: todo método público de un controlador es una acción visible desde el exterior, esto quiere decir que yo podría desde el navegador invocar ese método sin problema, más adelante vamos a ver la forma de evitarlo.

Cómo se invoca una acción de un controlador?

Nuevamente por convención, si vamos al navegador y escribimos

http://servidor:puerto/nombreControlador/nombreAccion

Vamos a invocar nuestro código, en este ejemplo sería:

http://localhost:62078/home/index

donde “home” es por HomeController e “index” el por el método Index, de esta manera ASP.NET MVC sabe que tiene que crear una instancia del controlador y llamar al método, siempre y cuando el controlador se llame HomeController, la acción sea un método público y el controlador se encuentre dentro de la carpeta “Controllers

Cómo se invoca una vista?

Si escribimos la dirección http://localhost:62078/home/index en el navegador nuevamente recibimos un error, esto es porque el controlador recibe la petición (llama al modelo que en este caso no existe) y retorna una vista, es claro que no hemos definido ninguna vista aún es por eso que falla, vamos a hacer

Creando una vista

La forma sencilla de crear una vista el posicionar el mouse sobre el método Index, presionar botón derecho y seleccionar “add view

image

Vemos que aparece una ventana con opciones y nos sugiere el nombre “Index” para la vista para que coincida con el de la acción (otra convención) destildamos la opción marcada y hacemos click en Add

image

Visual Studio crea la vista y la ubica dentro de la carpeta Views y crea una subcarpeta Home, que coincide con el nombre del controlador (otra convención)

Es por todas estas convenciones que la acción Index del controlador Home pude encontrar la vista correspondiente (si bien podríamos forzar otra)

image

No nos detengamos ahora en la vista, simplemente agreguemos dentro del div el mensaje “Hola MVC” y corramos la aplicación con F5

image

Ahora si funciona, lo que pasó fue que se invocó la acción Index del controlador Home y esta retornó la vista Index, realmente no tuvimos que configurar nada para que todo esto ocurra, mágico.

Por último dejo un video con el mismo ejemplo.

Nos leemos en la próxima.

ASP.NET MVC Series–El patrón MVC

ASP.NET MVC es una implementación del patrón de diseño MVC, el cual separa la aplicación en tres componente, el modelo la vista y el controlador.

Parte a parte

La vista es la representación de los datos, el ejemplo más claro en una aplicación web es el HTML de la pantalla, pero podría ser tranquilamente un JSON que expone una API.

El modelo es todo el dominio de la aplicación, con sus datos, su comportamiento y todo lo necesario para solucionar el problema de negocios, sin necesidad de ninguno de los otros dos componentes.

El controlador simplemente vincula la vista y el modelo, se encarga de recibir las peticiones del usuario (en una aplicación web serían las peticiones HTTP, por ejemplo cuando un usuario coloca una dirección URL o presiona un link, en el ejemplo de la API la invocación de un método de la misma) y retornar el resultado del modelo a la vista, de esto podemos sacar conclusiones importantes:

  • El modelo pude (y debería) funcionar sin la vista ni el controlador.
  • La vista no conoce el modelo, sino que recibe datos del controlador. (no siempre los datos que recibe una vista son objetos del modelo)
  • El modelo no recibe nunca una petición directa de la vista, todo llega a través del controlador.
  • El modelo representa todo el negocio.
  • Nunca debería existir lógica de negocios en el controlador.

Otras características

Gran extensiblidad

Vamos a ver que el framework está pensado de una manera en que todo se puede cambiar, si bien casi siempre los componentes que trae resuelven nuestro problema, para aquellos casos en que no sea así o queramos algo especial podemos hacerlo gracias a su capacidad de extensibilidad.

Convención sobre configuración

En general se busca minimizar la configuración necesaria y muchas del comportamiento se define por convención, por ejemplo: cuando se escribe la URL.

http://sitio.com/usuarios/list

ASP.NET MVC sabe que tiene que instanciar el controlador UsuariosController e invocar el método List, ya que así está definido por convención.

Hay muchas convenciones, las vamos a ir viendo a su tiempo, de todos modos casi siempre es posible modificar este comportamiento por defecto.

Motor de vistas

Una de las tres partes del patrón es la vista, existe una sintaxis especial programar en la vista (además del HTML) en el caso de ASP.NET MVC es posible cambiar el motor que interpreta lo que escribimos en la vista, por defecto tenemos dos, el mismo de Webforms que se llama ASP.NET y uno especialmente pensado para MVC que se llama Razor.

Motor de rutas

La forma de saber qué controlador será invocado cuando el usuario escriba una URL en el navegador es definida por el motor de ruteo, es muy flexible y permite hacer cosas muy interesantes que ayudan a la organización y a SEO

HTMLHelpers

Dentro de la vista no tenemos la posibilidad de usar controles como en Webforms pero podemos utilizar los llamados HTMLHelpers que son algo similar y permiten hacer cosas como generar el HTML de un combo (elemento select de HTML) a partir de un IEnumerable<T>, también podemos crear nuestros propios HTMLHelpers.

Action Filters

Las acciones del usuario llegan al controlador, esto lo sabemos, pero existe otro componente que recibe antes las invocaciones y también puede modificar las respuestas del controlador, se llaman intercepting filters según la definición del patrón MVC, en el caso de ASP.NET MVC se los llama Action Filters y permite hacer cosas como decorar un método del un controlador con una atributo y que esto impida que se llame al método sin tener una cookie dada ya que la llamada es recibida primero por el Action Filter, también podemos manipular la respuesta del controlador y agregarle un META TAG al HTML resultante o cualquier otra cosa que necesitemos.

Model Binder

Este componente se encarga de recibir los datos enviados por el usuario (tanto por GET como por POST, etc.) y generar un objeto a partir de ellos, es decir, si un controlador espera que el usuario le envíe un objeto “Mensaje” el model binder va a intentar crear uno y llenarlo con los datos que se enviaron en el request HTTP, vamos a verlo en más detalle después pero es casi mágico.

Action Result

Cuando un controlador consulta al modelo y éste devuelve un resultado, está listo para mostrarlo al usuario, la respuesta del controlador siempre se basa en un ActionResult, que no es más que un tipo que representa una respuesta HTTP, todos los tipos de resultados (o casi) heredan de ActionResult, el más común es el ViewResult que retorna una representación HTML, pero hay otros como por ejemplo JSONResult que devuelve un JSON, de nuevo, vamos a verlo más en detalle después.

image

El modelo quedaría más o menos así (simplificado y levemente modificado para mejor compresión)

Hay más

Existen otros componentes y muchos detalles que vamos a ir viendo más adelante, de momento con esto podemos empezar a meter mano en el código.

Nos leemos.

ASP.NET MVC Series–Qué es ASP.NET MVC?

Comenzamos esta serie bien desde el principio, contestando algunas grandes preguntas:

  • Qué es ASP.NET MVC y para qué sirve?
  • Es lo mismo que ASP?
  • Es lo mismo que ASP.NET?
  • Qué ventajas tengo si lo uso?
  • Qué desventajas tengo si lo uso?
  • A partir de ahora lo uso para todos los sitios web que voy a hacer?
  • Es gratis, open source, qué hace falta para usarlo?

Vamos a empezar a contestarlas de a una.

image

Qué es ASP.NET MVC?

ASP.NET MVC es un framework de desarrollo web desarrollado por Microsoft, está construido sobre ASP.NET y es una implementación del patrón Model View Controller, actualmente nos encontramos en la versión 4 de este producto.

Sirve para hacer aplicaciones Web de todo tipo y en su última versión permite hacer servicios REST de forma muy sencilla.

Es lo mismo que ASP?

No, ASP o ASP 3 o también conocido como ASP clásico es algo bien diferente y no tiene nada que ver con el mundo .net, si bien ASP.NET supone una evolución del otro.

Es lo mismo que ASP.NET?

No, en ASP.NET MVC no existen los webforms ni los componentes ni los eventos ni el viewstate como se conocen en ASP.NET, si bien está construido sobre ASP.NET y esto implica que tienen mucho en común la idea es bien distinta debido al patrón que utilizan.

Qué ventajas tengo si lo uso?

La principal ventaja es la utilización del patrón MVC que permite organizar la aplicación de un modo más claro, donde cada parte tiene su responsabilidad, esto permite además, utilizar pruebas unitarias sobre el modelo si aplicamos bien el patrón, y también trabajar casi sin pensar en la presentación, vuelvo a aclarar, siempre que se utilice bien el patrón.

Además tenemos total control de lo que ocurre, a diferencia de ASP.NET webforms en donde muchas cosas están fuera de nuestro control.

Por último es extremadamente extensible, lo que no hace el framework tal cual se ofrece podemos hacerlo con algún componente externo o hacerlo nosotros, esto incluye el manejo de rutas, los filtros, tipos de resultados, etc.

Qué desventajas tengo si lo uso?

La principal desventaja es que es más complejo lograr cosas que con ASP.NET con webforms son muy sencillas como por ejemplo conectar a una base de datos y mostrar en una grilla, la otra desventaja es que es necesario un mayor conocimiento de HTTP para lograr aprovechar el potencial de la herramienta.

A partir de ahora lo uso para todos los sitios web que voy a hacer?

Una gran pregunta, en mi opinión la respuesta es que no, sin embargo para la gran mayoría de las aplicaciones que vamos a hacer normalmente es lo más indicado, pero puede haber casos de armar un prototipo rápido o una herramienta para llenar datos en la que webforms o algo basado en componentes sería más rápido de implementar y más adecuado.

Es gratis, open source, qué hace falta para usarlo?

En principio es un framework construido sobre ASP.NET MVC que es open source, sin embargo hace falta .NET 2 o superior para correrlo (o Mono) por lo tanto es necesario por lo menos IIS 6 (se puede hacer funcionar MVC 1 en IIS 5 con un poco de configuración)

Si queremos utilizar el patrón MVC en .NET 1.1 tenemos que utilizar alguna otra implementación como por ejemplo Monorail

Por último

Según mi experiencia hoy por hoy la forma de hacer una aplicación web con el stack .NET es con MVC, si bien ASP.NET webforms ha ido evolucionando sigue teniendo lo que para mí son grandes contras, la cantidad de HTML que genera de más, problemas de compatibilidad con browsers de algunos componentes y la falta de control sobre el comportamiento de algunas cosas (el ciclo de vida de ciertos componentes no es igual que el del webforms, etc) ASP.NET MVC permite ir a una arquitectura más clara y escalable (no digo que no se pueda con ASP.NET webforms pero hay que poner mucho del lado de uno ya que el framework no está pensado así) y utilizar prácticas más profesionales como test unitarios en prácticamente todas las partes de la aplicación.

Además ASP.NET MVC es muy extensible y podemos controlar prácticamente todo el comportamiento, mi consejo es usarlo siempre que sea posible.

Hasta la próxima.