ASP.NET MVC y Ajax: fácil no… facilísimo :)

Hola a todos amigos! 😉

El comentario de Gabriel en este post de mi blog (http://geeks.ms/blogs/etomas/archive/2009/04/02/asp-net-mvc-controles-chart-y-ajax.aspx) me ha motivado a escribir la siguiente entrada.

Él preguntaba sobre si los controles Ajax de ASP.NET, como p.ej. UpdatePanel se podían usar bajo el framework MVC. No conozco mucho los controles de la Ajax Library porque personalmente no me interesan demasiado, aunque apuesto que la mayoría usan viewstate así que me imagino que no deben poder usarse bajo MVC…

… por otro lado sobreentiendo que la duda de Gabriel, va un poco más allá y quiere saber como usar Ajax con el framework MVC. Pues para verlo muy someramente aquí va esta entrada.

El soporte para Ajax del framework MVC no es que sea espectacular: las vistas tienen una propiedad Ajax que permite acceder al objeto AjaxHelper, que contiene varios métodos para permitir usar Ajax en el framework MVC. P.ej. si quieres poner un link que al pulsarlo cargue el div cuyo id sea “ajaxpanel” puedes hacer:

<%=Ajax.ActionLink("Pulsa aquí", "view1", new AjaxOptions() 
{ UpdateTargetId="ajaxpanel"}) %>

Al pulsar sobre el enlace, el framework MVC ejecutará la acción “view1” (del controlador actual) y la vista que esta acción devuelva será incrustada dentro del elemento DOM cuyo id sea ajaxpanel.

No está mal, pero tiene dos pegas:

  1. De serie no nos viene nada más: si queremos usar imágenes que sean enlaces Ajax, o botones, o una combo, debemos hacerlo nosotros.
  2. Usa la librería propia de Ajax de MS (MicrosoftAjax.js y MicrosoftMvcAjax.js)… No tengo nada personal en contra de esta librería, pero no veo muy claro a que viene: ¿teniendo jQuery, para que reinventar la rueda?

Yo personalmente uso sólo jQuery para mi soporte Ajax… ¿Por qué? Pues porqué me da todo lo que necesito… y más. Además de que es cross-browser y no sólo ofrece temas para Ajax, sino para muchas otras cosas. Si estás desarrollando web y no usas jQuery cuando empieces te preguntarás como has podido estar sin ella todo este tiempo.

Usar jQuery implica que no usamos las funciones del AjaxHelper, pero bueno no importa demasiado: rehacerlas usando jQuery no cuesta nada… ah! Y además jQuery ya viene con el framework MVC (en la carpeta /scripts).

En esta demo, veremos como hacer en un momento una vista con dos botones: al pulsar cada uno de ellos se cargará via Ajax una vista y se incrustará dentro de un div.

1. Inicio: Modificación de la vista master

Creamos una nueva aplicación ASP.NET MVC. Ello nos creará la aplicación inicial, con varias vistas (login, home, registro) para empezar a trabajar. Vamos a modificar directamente la vista inicial (Views/Home/Index.aspx).

Lo primero a hacer es incluir la carga de jQuery en nuestra vista. En mi caso modifico la vista master, para que jQuery esté incluida “de serie” en todas mis vistas… yo la uso a mansalva, y creedme: vais a terminar haciendo lo mismo 🙂

La vista master está en Views/Shared/Site.Master. Si la abrís vereis que tiene un poco de código. Podeis obviarlo, simplemente añadid una etiqueta <script> dentro del <head>:

<head runat="server">
    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" />
</
title> <link href="../../Content/Site.css"
rel="stylesheet" type="text/css" /> <%-- Incluimos jQuery --%> <script type="text/javascript" src="../../Scripts/jquery-1.3.2.js">
</
script>
</head>

(En este caso incluyo jquery-1.3.2.js que es la versión que viene junto con el framework MVC).

2. Modificación de la vista inicial

Como comenté en el punto anterior vamos a trabajar modificando directamente la vista inicial (Views/Home/Index.aspx). Para ello vamos a añadir simplemente dos botones y un <div> vacío que será nuestro contenedor ajax:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
Inherits="System.Web.Mvc.ViewPage" %> <asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent"
runat="server"> Home Page </asp:Content> <asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server"> <h2>Pulsa los botones para refrescar el div usando ajax</h2> <input type="button" id="view1" value="Vista 1" /> <input type="button" id="view2" value="Vista 2"/> <%-- Este es el div que vamos a modificar via ajax --%> <div id="ajaxpanel" style="border-color:red; border-style:solid;
border-width:thin"></div> </asp:Content>

He puesto un border rojo al div para que vea (sí, reconozco que el diseño no es mi fuerte :p).

2.1 Crear las llamadas Ajax al pulsar los botones

Ahora vamos a añadir código javascript para que cuando se pulsen los botones se hagan las llamadas ajax… Si ya estás corriendo a meter un onClick en cada <input> tranquilo: bienvenido al mundo de jQuery 🙂

Este es el código javascript que puedes colocar en tu página (justo antes del tag <h2>, dentro del asp:Content IndexContent):

<script type="text/javascript">
    $(document).ready(function() {
        $("#view1").click(function() {
            $("#ajaxpanel").load("<%=Url.Action("View1") %>");
        });
        $("#view2").click(function() {
            $("#ajaxpanel").load("<%= Url.Action("View2") %>");
        });
    });
</script>

Vamos a comentar rápidamente este código… aunque es muy simple muestra dos conceptos clave de jQuery: los selectores y la potencia de sus funciones incorporadas.

El $ es el simbolo “jQuery” por excelencia. $(document) me devuelve un manejador al documento actual. La función ready() espera como parámetro otra función que se ejecutará cuando el documento esté cargado y todos los objetos DOM existan.

En mi caso le paso a la función ready una función anónima que hace lo que a mi me interesa que se haga cuando el documento esté cargado: crear funciones gestoras de los click de los botones para que se llame via Ajax a otras URLs.

El código $(“#view1”) es un selector: los selectores son una de las claves de jQuery, ya que permiten obtener un manejador jQuery a uno o varios objetos DOM para realizar tareas con ellos. Aquí estoy usando uno de los más simples, el # que devuelve un manejador al objeto DOM cuyo ID sea la cadena que hay después de #. Así $(“#view1”) me devuelve un manejador al objeto DOM cuyo id sea “view1”, que en mi caso es el primer boton.

Una vez tengo un manejador de jQuery puedo hacer barbaridad de cosas con él (que afectarán al objeto (u objetos) DOM a los que apunte dicho manejador). En mi caso llamo a la función click que espera como parámetro otra función. La función click lo que hace es ejecutar la función que se pase como parámetro cuando se lance el evento click del elemento DOM subyacente… Y que le paso como parámetro a la función click? Pues otra función anónima con el código a ejecutar cuando se lance el evento. ¿Y qué codigo es este? Pues usar un selector para obtener un manejador al objeto cuyo ID sea “ajaxpanel” (que es el <div>) y llamar el método load. El método load usa Ajax para cargar la URL especificada y incrustar el resultado dentro del DOM del manejador usado. Es decir, en nuestro caso dentro del div.

Ya casi estamos…

3. Crear las acciones en el controlador

En ASP.NET MVC las URLs se mapean a acciones de los controladores, no a archivos físicos .aspx. Si os fijais en el codigo de la vista se ha usado <%= Url.Action(“xxx”) %> para pasar la URL al método load de jQuery. Esta llamada a URL.Action obtiene la URL de la acción indicada del controlador actual. En mi caso he llamado a las acciones “View1” y “View2”.

Dado que estamos en una vista gestionada por el controlador Home, debemos crear las acciones en el controlador HomeController. La forma más simple de crear una acción es definir un método público en dicho controlador. Así, pues definimos los métodos View1 y View2 en HomeController (que está dentro de la carpeta Controllers):

public ActionResult View1()
{
    return PartialView("View1");
}
public ActionResult View2()
{
    return PartialView("View2");
}

En este caso las dos acciones son bastante tontas: el controlador no hace nada salvo retornar dos vistas, llamadas View1 y View2. El método PartialView se usa cuando lo que se va a devolver es una vista parcial, esto es una vista que no es un HTML completo sino una parte.

Solo nos queda una pequeña cosa… crear las dos vistas!

4. Crear las dos vistas parciales

Vamos a crear las dos vistas que necesitamos. Dado que estamos creando vistas del controlador Home, debemos crearlas dentro de Views/Home. Para ello hacemos click con el botón derecho en la carpeta Home en el Solution Explorer y seleccionamos la opción Add->View. Esto nos despliega el cuadro de nueva vista de ASP.NET MVC.

image

Damos nombre a la vista (View1) y marcamos la checkbox de “Create a partial view”. Con ello nos va a crear un archivo .ascx, en lugar de un .aspx (que sería una página completa).

Yo he añadido el siguiente código a mi vista View1:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<h1>Esta es la vista1</h1>

Ya veis… poca cosa, no?

Repetid el proceso para crear la View2 y… ya habeis terminado.

Ejecutad el proyecto y os aparecerá la página principal, con los dos botones. Pulsad uno u otro y observad como el div se rellena via Ajax con el código de cada vista.

En la última imagen os dejo una captura con el firebug donde se ve la última petición ajax:

image

Esto ha sido una muy breve introducción… pero espero que os haya servido para que os entre el gusanillo de ASP.NET MVC!!! 😉

Saludos!

19 comentarios en “ASP.NET MVC y Ajax: fácil no… facilísimo :)”

  1. Hola, gracias por este quickstart, me parece muy claroy directo al problema que se quiere aprender a resolver.

    acabo de recomendarselo a algunos amigos.
    Saludos.

  2. soy principiante en eso de ajax estoy investigando tengo que aplicar ajax donde utilizo calendarios y me y botones y me provoca refresh. algun manual interesante para esto
    gracias

  3. Otro fantástico articulo!

    Mira una pregunta… que le estoy dando vueltas a SilverLight. Dado que con dicha tecnología el peso de la presentación cae del lado del cliente, ¿tiene sentdio la integración Asp.Net MVC con SilverLight? ¿Y para redondear la cosa… IoC? (Recalco el fabulos articulo donde explicaste la integración MVC con IoC)

    Saludos!

  4. @Galcet
    ¿Integración MVC con Silverlight? Simplificando el tema, podríamos decir que hay “dos usos” de Silverlight: O bien incrustas “zonas” Silverlight en una web tradicional (webforms o MVC) o bien creas toda tu aplicación web usando Silverlight.
    Si creas toda tu web usando Silverlight no tienes integración con MVC puesto que no vas a tener MVC: tu punto de entrada a la aplicación será una única URL y a partir de este punto Silverlight tomará el control.
    Silverlight traslada al cliente la presentación, incluyendo la lógica asociada a presentación y se puede trasladar también lógica de negocio. Cuando desarrollas con Silverlight puedes (y deberías :p) aplicar todos los conceptos clásicos de separated presentation (MVP o MVVM), IoC y demás: p.ej. hay una versión de PRISM para Silverlight y Caliburn también trabaja bien con Silverlight.
    Desde este punto de vista, Silverlight no es un sustituto de html: va un paso más allá. Nuestra aplicación es 100% Silverlight y se comunica con el servidor mediante servicios web. A grandes rasgos es la misma aplicación que tendríamos en una aplicación winforms que trabajase consumiendo servicios web y que no guardase datos en local. El desarrollo Silverlight se asemeja más al desarrollo en winforms, que al desarrollo en webforms/MVC.

    Otro caso es cuando “incrustas” zonas Silverlight en tu web. En este caso tienes una aplicación web clásica (webforms o MVC) en la cual algunas zonas en lugar de estar renderizadas usando html, lo están usando Silverlight. La comunicación entre Silverlight y el servidor puedes hacerla usando servicios web como en el caso anterior, y también puedes comunicar la zona silverlight con la “zona html” usando javascript.
    En este caso tampoco hay realmente una integración de MVC con Silverlight: tu aplicación es 100% MVC, con la particularidad de que vas a tener “zonas” renderizadas por Silverlight, pero desde Silverlight no vas a llamar a ningún controlador ni nada parecido.
    En este caso, generalmente a Silverlight se le asignan tareas de presentación pura (un gráfico espectacular, un banner, …).

    Evidentemente hay toda gama de grises: puedo tener una aplicación MVC con zonas Silverlight y esas zonas pueden ser muuuuuuucho más complejas que un simple gráfico (tan complejas que *a lo mejor* debería aplicar conceptos de MVP/MVVM a cada zona en particular, puesto que realmente son mini-aplicaciones).

    No se si me he explicado bien…
    Un saludo!

  5. Te has explicado perfecto… ahora soy yo el que debe asumir y entender todo este ‘nuevo’ mundo que es SilverLight para mi.

    Mil Gracias!

  6. Hola, tenia las mismas dudas que Galcet y creo que las has aclarado extraordinariamente con tu respuesta, por lo menos para mi que soy nuevo en SilverLight me ha servido de mucho. Yo particularmente suelo trabajar con Monorail y me preguntaba que tal se llevarian juntos, pero ya veo que Silverlight es otra cosa, que va mas alla de un JS “hormonado”.

    Un saludo.

  7. Disculpa la molestia soy nuevo en este mundo de .Net MVC y quisiera saber si me puedes proporcionar un ejemplo un poco mas completo de .net MVC y jQuery…

  8. @Leonardo
    Justo hoy Lunes 28 a las 20:00 hora española realizo un WebCast para la gente del UoC DotNetClub donde hablo de ASP.NET MVC… evidentemente jQuery y Ajax estará entre los temas que trataremos!
    El WebCast se grabará, por lo que si no se puede assistir en directo se podrá ver a posteriori.
    Tines más detalles en https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032454315&Culture=es-ES que es la URL de registro.
    Un saludo!

  9. @Alejandro
    A que te refieres exactamente? A como pasarle parámetros a View1 desde Ajax, usando el Ajax.ActionLink??
    O te refieres a algo distinto???

    Dímelo please!! 😉

    Un saludo y gracias por comentar!

  10. Saludos! Tengo una duda parecida a la de Alejandro. ¿Podría enviar como parámetro a alguna de las vistas, por ejemplo, un HttpPostedFileBase? Como para poder mostrar dinámicamente una imagen, agregando al Url.Action un parámetro.

  11. Muy buen post, muchas gracias.
    Una vez que se actualiza y muestra información en el div del ajaxpanel, ¿Cómo puedo ejecutar un JavaScript?
    Por ejemplo, dependiendo de si existe determinado dato en el ajaxpanel, habilitar algun boton. Gracias

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *