Usar o AJAX para fornecer atualizações dinâmicas
pela Microsoft
Esta é a etapa 10 de um tutorial gratuito de aplicativo "NerdDinner" que explica como criar um aplicativo Web pequeno, mas completo, usando ASP.NET MVC 1.
A Etapa 10 implementa o suporte para usuários conectados ao RSVP seu interesse em participar de um jantar, usando uma abordagem baseada em Ajax integrada na página de detalhes do jantar.
Se você estiver usando ASP.NET MVC 3, recomendamos que siga os tutoriais do Introdução With MVC 3 ou MVC Music Store.
Etapa 10 do NerdDinner: AJAX habilitando aceitações de RSVPs
Agora, vamos implementar o suporte para usuários conectados ao RSVP seu interesse em participar de um jantar. Habilitaremos isso usando uma abordagem baseada em AJAX integrada na página de detalhes do jantar.
Indicando se o usuário é RSVP'd
Os usuários podem visitar a URL /Dinners/Details/[id] para ver detalhes sobre um jantar específico:
O método de ação Details() é implementado da seguinte maneira:
//
// GET: /Dinners/Details/2
public ActionResult Details(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (dinner == null)
return View("NotFound");
else
return View(dinner);
}
Nossa primeira etapa para implementar o suporte a RSVP será adicionar um método auxiliar "IsUserRegistered(username)" ao nosso objeto Dinner (dentro da classe parcial Dinner.cs que criamos anteriormente). Esse método auxiliar retorna true ou false dependendo se o usuário é atualmente RSVP'd para o Jantar:
public partial class Dinner {
public bool IsUserRegistered(string userName) {
return RSVPs.Any(r => r.AttendeeName.Equals(userName, StringComparison.InvariantCultureIgnoreCase));
}
}
Em seguida, podemos adicionar o seguinte código ao nosso modelo de exibição Details.aspx para exibir uma mensagem apropriada indicando se o usuário está registrado ou não para o 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.
<% } %>
E agora, quando um usuário visitar um Jantar para o qual ele está registrado, ele verá esta mensagem:
E quando visitarem um jantar para o qual não estão registrados, verão a mensagem abaixo:
Implementando o método Register Action
Agora, vamos adicionar a funcionalidade necessária para habilitar os usuários ao RSVP para um jantar na página de detalhes.
Para implementar isso, criaremos uma nova classe "RSVPController" clicando com o botão direito do mouse no diretório \Controllers e escolhendo o comando de menu Adicionar Controlador>.
Implementaremos um método de ação "Register" na nova classe RSVPController que usa uma ID para um Dinner como argumento, recupera o objeto Dinner apropriado, verifica se o usuário conectado está atualmente na lista de usuários que se registraram para ele e, se não adicionar um objeto RSVP para eles:
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 acima como estamos retornando uma cadeia de caracteres simples como a saída do método de ação. Poderíamos ter inserido essa mensagem em um modelo de exibição , mas como ela é tão pequena, usaremos apenas o método auxiliar Content() na classe base do controlador e retornaremos uma mensagem de cadeia de caracteres como acima.
Chamando o método de ação RSVPForEvent usando a AJAX
Usaremos o AJAX para invocar o método de ação Register de nossa exibição Detalhes. Implementar isso é muito fácil. Primeiro, adicionaremos duas referências da biblioteca de scripts:
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
A primeira biblioteca faz referência ao núcleo ASP.NET biblioteca de scripts do lado do cliente AJAX. Esse arquivo tem aproximadamente 24 mil de tamanho (compactado) e contém a funcionalidade principal do AJAX do lado do cliente. A segunda biblioteca contém funções de utilitário que se integram ao ASP.NET métodos auxiliares AJAX internos do MVC (que usaremos em breve).
Em seguida, podemos atualizar o código do modelo de exibição que adicionamos anteriormente para que, em vez de gerar uma mensagem "Você não está registrado para este evento", renderizemos um link que, quando enviado por push, executa uma chamada AJAX que invoca nosso método de ação RSVPForEvent em nosso controlador RSVP e RSVPs o usuário:
<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>
O método auxiliar Ajax.ActionLink() usado acima é interno ASP.NET MVC e é semelhante ao método auxiliar Html.ActionLink(), exceto que, em vez de executar uma navegação padrão, ele faz uma chamada AJAX para o método de ação quando o link é clicado. Acima, estamos chamando o método de ação "Register" no controlador "RSVP" e passando o DinnerID como o parâmetro "id" para ele. O parâmetro final AjaxOptions que estamos passando indica que queremos pegar o conteúdo retornado do método de ação e atualizar o elemento HTML <div> na página cuja ID é "rsvpmsg".
E agora, quando um usuário navega para um jantar para o qual ainda não está registrado, ele verá um link para RSVP para ele:
Se clicarem no link "RSVP para este evento", eles farão uma chamada AJAX para o método de ação Register no controlador RSVP e, quando ele for concluído, verão uma mensagem atualizada como abaixo:
A largura de banda de rede e o tráfego envolvidos ao fazer essa chamada AJAX são muito leves. Quando o usuário clica no link "RSVP para este evento", uma pequena solicitação de rede HTTP POST é feita para a URL /Dinners/Register/1 que se parece com a seguinte na transmissão:
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
E a resposta do nosso método de ação Register é simplesmente:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 29
Thanks - we'll see you there!
Essa chamada leve é rápida e funcionará mesmo em uma rede lenta.
Adicionando uma animação jQuery
A funcionalidade do AJAX que implementamos funciona bem e rapidamente. Às vezes, pode acontecer tão rápido, porém, que um usuário pode não notar que o link RSVP foi substituído por um novo texto. Para tornar o resultado um pouco mais óbvio, podemos adicionar uma animação simples para chamar a atenção para a mensagem de atualização.
O modelo de projeto padrão ASP.NET MVC inclui jQuery – uma excelente (e muito popular) biblioteca JavaScript código aberto que também é compatível com a Microsoft. O jQuery fornece uma série de recursos, incluindo uma boa biblioteca de efeitos e seleção de DOM HTML.
Para usar o jQuery, primeiro adicionaremos uma referência de script a ele. Como usaremos o jQuery em uma variedade de locais em nosso site, adicionaremos a referência de script em nosso Site. master master arquivo de página para que todas as páginas possam usá-lo.
<script src="/Scripts/jQuery-1.3.2.js" type="text/javascript"></script>
O código escrito usando JQuery geralmente usa um método JavaScript "$()" global que recupera um ou mais elementos HTML usando um seletor CSS. Por exemplo, $("#rsvpmsg") seleciona qualquer elemento HTML com a id de rsvpmsg, enquanto $(".something") selecionaria todos os elementos com o nome da classe CSS "something". Você também pode escrever consultas mais avançadas, como "retornar todos os botões de opção verificados" usando uma consulta seletora como: $("input[@type=radio][@checked]").
Depois de selecionar elementos, você pode chamar métodos neles para executar uma ação, como escondê-los: $("#rsvpmsg"). hide();
Para nosso cenário de RSVP, definiremos uma função JavaScript simples chamada "AnimateRSVPMessage" que seleciona o div> "rsvpmsg" <e anima o tamanho de seu conteúdo de texto. O código abaixo inicia o texto pequeno e, em seguida, faz com que ele aumente em um período de tempo de 400 milissegundos:
<script type="text/javascript">
function AnimateRSVPMessage() {
$("#rsvpmsg").animate({fontSize: "1.5em"},400);
}
</script>
Em seguida, podemos conectar essa função JavaScript a ser chamada depois que nossa chamada AJAX for concluída com êxito passando seu nome para nosso método auxiliar Ajax.ActionLink() (por meio da propriedade de evento "OnSuccess" do AjaxOptions):
<%= Ajax.ActionLink( "RSVP for this event",
"Register", "RSVP",
new { id=Model.DinnerID },
new AjaxOptions { UpdateTargetId="rsvpmsg",
OnSuccess="AnimateRSVPMessage"}) %>
E agora, quando o link "RSVP para este evento" for clicado e nossa chamada AJAX for concluída com êxito, a mensagem de conteúdo enviada de volta animará e aumentará:
Além de fornecer um evento "OnSuccess", o objeto AjaxOptions expõe eventos OnBegin, OnFailure e OnComplete que você pode manipular (juntamente com uma variedade de outras propriedades e opções úteis).
Limpeza – refatorar uma exibição parcial RSVP
Nosso modelo de exibição de detalhes está começando a ficar um pouco longo, o que tornará um pouco mais difícil de entender. Para ajudar a melhorar a legibilidade do código, vamos concluir criando uma exibição parcial – RSVPStatus.ascx – que encapsula todo o código de exibição RSVP para nossa página Detalhes.
Podemos fazer isso clicando com o botão direito do mouse na pasta \Views\Dinners e escolhendo o comando de menu Adicionar Exibição>. Teremos um objeto Dinner como seu ViewModel fortemente tipado. Em seguida, podemos copiar/colar o conteúdo RSVP de nossa exibição Details.aspx nele.
Depois de fazermos isso, também vamos criar outra exibição parcial – EditAndDeleteLinks.ascx – que encapsula nosso código de exibição de link Editar e Excluir. Também faremos com que ele pegue um objeto Dinner como seu ViewModel fortemente tipado e copie/cole a lógica Editar e Excluir de nossa exibição Details.aspx nele.
Nosso modelo de exibição de detalhes pode incluir apenas duas chamadas de método Html.RenderPartial() na 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>
Isso torna o código mais limpo para ler e manter.
Próxima etapa
Agora vamos examinar como podemos usar o AJAX ainda mais e adicionar suporte de mapeamento interativo ao nosso aplicativo.