Compartir a través de


Usar AJAX para entregar actualizaciones dinámicas

Por Microsoft

Descargar PDF

Este es el paso 10 de un tutorial de la aplicación "NerdDinner" gratuito que le guía en el proceso de creación de una aplicación web pequeña, pero completa, con MVC 1 de ASP.NET.

El paso 10 permite a los usuarios que hayan iniciado sesión confirmar su interés en asistir a una cena mediante un enfoque basado en Ajax integrado en la página de detalles de la cena.

Si usa MVC 3 de ASP.NET, le recomendamos que siga los tutoriales Introducción a MVC 3 o Almacén de música MVC.

Paso 10 de NerdDinner: Habilitación mediante AJAX de aceptaciones de reservas

Ahora vamos a permitir que los usuarios registrados confirmen su interés en asistir a una cena. Habilitaremos esto mediante un enfoque basado en AJAX integrado en la página de detalles de la cena.

Indicar si el usuario ha confirmado la reserva

Los usuarios pueden visitar la dirección URL /Dinners/Details/[id] para ver los detalles sobre una cena determinada:

Screenshot of the Nerd Dinner web page with details about the Dinner.

El método de acción Details() se ha implementado de la siguiente manera:

//
// GET: /Dinners/Details/2

public ActionResult Details(int id) {

    Dinner dinner = dinnerRepository.GetDinner(id);

    if (dinner == null)
        return View("NotFound");
    else
        return View(dinner);
}

Nuestro primer paso para implementar la compatibilidad con las reservas será agregar un método auxiliar "IsUserRegistered(username)" a nuestro objeto Dinner (dentro de la clase parcial Dinner.cs que creamos anteriormente). Este método auxiliar devuelve true o false en función de si el usuario está actualmente registrado para la cena:

public partial class Dinner {

    public bool IsUserRegistered(string userName) {
        return RSVPs.Any(r => r.AttendeeName.Equals(userName, StringComparison.InvariantCultureIgnoreCase));
    }
}

A continuación, podemos agregar el código siguiente a nuestra plantilla de vista Details.aspx para mostrar un mensaje adecuado que indique si el usuario está registrado o no para el evento:

<% if (Request.IsAuthenticated) { %>
 
    <% if (Model.IsUserRegistered(Context.User.Identity.Name)) { %>       

        <p>You are registred for this event!</p>
    
    <% } else {  %>  
    
        <p>You are not registered for this event</p>
        
    <% }  %>
    
<% } else { %>
 
    <a href="/Account/Logon">Logon</a> to RSVP for this event.

<% } %>

Y ahora, cuando un usuario visite una cena para la que está registrado, verá este mensaje:

Screenshot of the Nerd Dinners details page, the message You Are Registered For This Event is shown at the bottom.

Y cuando visite una cena para la que no está registrado, verá el siguiente mensaje:

Screenshot of the Nerd Dinners details page. The message You Are Not Registered For this Event is shown.

Implementación del método de acción Register

Ahora, vamos a agregar la funcionalidad necesaria para permitir que los usuarios confirmen su asistencia a una cena desde la página de detalles.

Para implementarlo, crearemos una nueva clase "RSVPController" haciendo clic con el botón derecho en el directorio \Controllers y eligiendo el comando de menú Agregar->Controlador.

Implementaremos un método de acción "Register" dentro de la nueva clase RSVPController que toma un identificador de una cena como argumento, recupera el objeto Dinner adecuado, comprueba si el usuario que ha iniciado sesión está actualmente en la lista de usuarios que se han registrado y, si no, agrega un objeto RSVP para él:

public class RSVPController : Controller {

    DinnerRepository dinnerRepository = new DinnerRepository();

    //
    // AJAX: /Dinners/RSVPForEvent/1

    [Authorize, AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Register(int id) {

        Dinner dinner = dinnerRepository.GetDinner(id);

        if (!dinner.IsUserRegistered(User.Identity.Name)) {
        
            RSVP rsvp = new RSVP();
            rsvp.AttendeeName = User.Identity.Name;

            dinner.RSVPs.Add(rsvp);
            dinnerRepository.Save();
        }

        return Content("Thanks - we'll see you there!");
    }
}

Observe más arriba cómo se devuelve una cadena simple como salida del método de acción. Podríamos haber insertado este mensaje dentro de una plantilla de vista, pero dado que es tan pequeño, solo usaremos el método auxiliar Content() en la clase base del controlador y devolveremos un mensaje de cadena similar al anterior.

Llamada al método de acción RSVPForEvent mediante AJAX

Usaremos AJAX para invocar el método de acción Register desde nuestra vista Details. Implementar esto es bastante fácil. En primer lugar, agregaremos dos referencias de biblioteca de scripts:

<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>

La primera biblioteca hace referencia a la biblioteca de scripts básica del lado cliente de AJAX de ASP.NET. Este archivo tiene aproximadamente un tamaño de 24 K y contiene la funcionalidad básica de AJAX del lado cliente. La segunda biblioteca contiene funciones de utilidad que se integran con los métodos auxiliares integrados de AJAX de MVC de ASP.NET (que usaremos en breve).

A continuación, podemos actualizar el código de la plantilla de vista que agregamos anteriormente para que en lugar de generar el mensaje "No está registrado para esto evento", en su lugar representamos un vínculo que, cuando se pulsa, realiza una llamada AJAX que invoca nuestro método de acción RSVPForEvent en nuestro controlador RSVP y confirma la asistencia del usuario:

<div id="rsvpmsg">

<% if(Request.IsAuthenticated) { %>
 
    <% if(Model.IsUserRegistered(Context.User.Identity.Name)) { %>       

        <p>You are registred for this event!</p>

    <% } else { %>  
    
        <%= Ajax.ActionLink( "RSVP for this event",
                             "Register", "RSVP",
                             new { id=Model.DinnerID }, 
                             new AjaxOptions { UpdateTargetId="rsvpmsg"}) %>         
    <% } %>
    
<% } else { %>
 
    <a href="/Account/Logon">Logon</a> to RSVP for this event.

<% } %>
    
</div>

El método auxiliar Ajax.ActionLink() utilizado anteriormente está integrado en MVC de ASP.NET y es similar al método auxiliar Html.ActionLink(), excepto que, en lugar de realizar una navegación estándar, realiza una llamada AJAX al método de acción cuando se hace clic en el vínculo. Más arriba se llama al método de acción "Register" en el controlador "RSVP" y se pasa el valor de DinnerID como el parámetro "id". El parámetro AjaxOptions final que estamos pasando indica que queremos tomar el contenido devuelto desde el método de acción y actualizar el elemento <div> de HTML de la página cuyo identificador es "rsvpmsg".

Y ahora, cuando un usuario navega a una cena para la que aún no está registrado, verá un vínculo para confirmar la asistencia a la misma:

Screenshot of the Nerd Dinners page with the R S V P button at the bottom.

Si hace clic en el vínculo "RSVP for this event", realizará una llamada AJAX al método de acción Register en el controlador RSVP y, cuando finalice, verá un mensaje actualizado como el siguiente:

Screenshot of the Nerd Dinner details page with the message Thanks We Will See You There at the bottom.

El ancho de banda de red y el tráfico implicados al realizar esta llamada AJAX es realmente ligero. Cuando el usuario hace clic en el vínculo "RSVP for this event", se realiza una pequeña solicitud de red HTTP POST a la dirección URL /Dinners/Register/1 similar a la siguiente en la conexión:

POST /Dinners/Register/49 HTTP/1.1
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Referer: http://localhost:8080/Dinners/Details/49

Y la respuesta del método de acción Register es simplemente:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 29
Thanks - we'll see you there!

Esta llamada ligera es rápida y funcionará incluso en una red lenta.

Adición de una animación de jQuery

La funcionalidad AJAX que hemos implementado funciona bien y rápido. A veces puede ocurrir tan rápido que es posible que un usuario no observe que el vínculo RSVP se ha reemplazado por un nuevo texto. Para que el resultado sea un poco más obvio, podemos agregar una animación sencilla para llamar la atención respecto al mensaje de actualización.

La plantilla predeterminada de proyecto MVC de ASP.NET incluye jQuery, una biblioteca de JavaScript excelente (y muy popular) de código abierto que también es admitida por Microsoft. jQuery proporciona una serie de características, incluida una buena biblioteca de efectos y selección del DOM de HTML.

Para usarla biblioteca jQuery, primero agregaremos una referencia de script a ella. Dado que vamos a usar jQuery en una variedad de lugares dentro de nuestro sitio, agregaremos la referencia de script dentro de nuestro archivo de página maestra Site.master para que todas las páginas puedan usarla.

<script src="/Scripts/jQuery-1.3.2.js" type="text/javascript"></script>

El código escrito con JQuery suele usar un método de JavaScript global "$()" que recupera uno o varios elementos HTML mediante un selector CSS. Por ejemplo, $("#rsvpmsg") selecciona cualquier elemento HTML con el identificador rsvpmsg, mientras que $(".something") seleccionaría todos los elementos con el nombre de clase CSS "something". También puede escribir consultas más avanzadas como "devolver todos los botones de radio activados" mediante una consulta de selector como: $("input[@type=radio][@checked]").

Una vez que haya seleccionado elementos, puede llamar a métodos en ellos para tomar acciones, como ocultarlos: $("#rsvpmsg").hide();

Para nuestro escenario de confirmación de asistencia, definiremos una función simple de JavaScript llamada "AnimateRSVPMessage" que selecciona el elemento <div> "rsvpmsg" y anima el tamaño de su contenido de texto. El código siguiente inicia el texto en un tamaño pequeño y, a continuación, hace que aumente en un período de tiempo de 400 milisegundos:

<script type="text/javascript">

    function AnimateRSVPMessage() {
        $("#rsvpmsg").animate({fontSize: "1.5em"},400);
    }

</script>

A continuación, podemos conectar esta función de JavaScript para que se la llame después de que la llamada AJAX se complete correctamente pasando su nombre al método auxiliar Ajax.ActionLink() (mediante la propiedad del evento "OnSuccess" de AjaxOptions):

<%= Ajax.ActionLink( "RSVP for this event",
                     "Register", "RSVP",
                     new { id=Model.DinnerID }, 
                     new AjaxOptions { UpdateTargetId="rsvpmsg",
                                       OnSuccess="AnimateRSVPMessage"}) %>

Y ahora cuando se hace clic en el vínculo "RSVP for this event" y nuestra llamada AJAX se completa correctamente, el mensaje de contenido enviado de vuelta se animará y aumentará de tamaño:

Screenshot of the Nerd Dinners page with the message Thanks We Will See You There in large print at the bottom.

Además de proporcionar un evento "OnSuccess", el objeto AjaxOptions expone eventos OnBegin, OnFailure y OnComplete que puede controlar (junto con una variedad de otras propiedades y opciones útiles).

Limpieza: refactorización de una vista parcial de RSVP

Nuestra plantilla de vista de detalles empieza a ser un poco larga, lo que hará con el tiempo que sea un poco más difícil de entender. Para ayudar a mejorar la legibilidad del código, vamos a crear una vista parcial (RSVPStatus.ascx) que encapsula todo el código de la vista RSVP de nuestra página Details.

Para ello, haga clic con el botón derecho en la carpeta \Views\Dinners y, a continuación, elija el comando de menú Agregar>Vista. Haremos que tome un objeto Dinner como su elemento ViewModel fuertemente tipado. A continuación, podemos copiar y pegar el contenido de RSVP de nuestra vista Details.aspx en ella.

Una vez hecho esto, también vamos a crear otra vista parcial, EditAndDeleteLinks.ascx, que encapsula nuestro código de la vista para editar y eliminar vínculo. También haremos que tome un objeto Dinner como su elemento ViewModel fuertemente tipado y copiaremos y pegaremos la lógica para editar y eliminar de nuestra vista Details.aspx en ella.

Nuestra plantilla de vista de detalles solo incluye dos llamadas al método Html.RenderPartial() en la parte inferior:

<asp:Content ID="Title" ContentPlaceHolderID="TitleContent"runat="server">
    <%= Html.Encode(Model.Title) %>
</asp:Content>

<asp:Content ID="details" ContentPlaceHolderID="MainContent" runat="server">

    <div id="dinnerDiv">

        <h2><%=Html.Encode(Model.Title) %></h2>
        <p>
            <strong>When:</strong> 
            <%=Model.EventDate.ToShortDateString() %> 

            <strong>@</strong>
            <%=Model.EventDate.ToShortTimeString() %>
        </p>
        <p>
            <strong>Where:</strong> 
            <%=Html.Encode(Model.Address) %>,
            <%=Html.Encode(Model.Country) %>
        </p>
         <p>
            <strong>Description:</strong> 
            <%=Html.Encode(Model.Description) %>
        </p>       
        <p>
            <strong>Organizer:</strong> 
            <%=Html.Encode(Model.HostedBy) %>
            (<%=Html.Encode(Model.ContactPhone) %>)
        </p>
    
        <% Html.RenderPartial("RSVPStatus"); %>
        <% Html.RenderPartial("EditAndDeleteLinks"); %>
 
    </div>
         
</asp:Content>

Esto hace que el código sea más limpio para leerlo y mantenerlo.

siguiente paso

Ahora, veamos cómo podemos usar AJAX aún más y agregar compatibilidad con la asignación interactiva a nuestra aplicación.