ASP.NET MVC – asynchroniczne wysyłanie formularzy (AJAX) na przykładzie prostego ShoutBox’a

Podobnie jak w czystym ASP.NET, framework ASP.NET MVC pozwala na wysyłanie formularzy w tle. Załóżmy, że chcemy napisać shoutbox’a, w którym wysłanie wiadomości na serwer nie wymagałoby ponownego przeładowania całej strony. Zamiast definiowania formularza za pomocą Html.BeginForm, musimy skorzystać z Ajax.BeginForm:

<% using(Ajax.BeginForm("AddMessage",new AjaxOptions(){ OnComplete="OnFinish", UpdateTargetId="messages"}))
{ %>
// treść
<%}%>

Pierwszy parametr to nazwa akcji. W drugim parametrze przekazujemy klasę AjaxOptions określającą między innymi zdarzenie w JavaScript wywoływane po zakończeniu zapytania oraz identyfikator elementu modyfikowanego w trakcie wykonywania akcji. Stwórzmy więc prosty ShoutBox:

<div  id="messages" style="width: 350px; height: 80px; overflow:auto;">
<%Html.RenderPartial("Messages"); %>
</div>
<%
   using(Ajax.BeginForm("AddMessage",new AjaxOptions(){ OnComplete="OnFinish", UpdateTargetId="messages"}))
   { %>

   <%if(Page.User.Identity.IsAuthenticated==false){ %>
   Nick:
   <br />
   <%=Html.TextBox("Nick", "", new { maxlength = 50, style = "width:220px" })%>
   
   <%} %>
   <br />
   Wiadomość:
   <br />
   <%=Html.TextBox("Message", "Wpisz opinię, która pojawi się na mównicy...", new { maxlength = 500, title = "Wpisz opinię, która pojawi się na mównicy...", @class = "water", style = "width:220px" })%>
   
   
   <input type="submit"  value="Wyślij" />


<%} %>

Najpierw definiujemy element div z ID ustawionym na “messages”. Następnie tworzymy asynchroniczny formularz za pomocą Ajax.BeginForm. Zawartość formularza nie zawiera już żadnej nowości – jedynie standardowe pola: jedno na nick a drugie na wiadomość. Przyjrzyjmy się jeszcze akcji AddMessage:

public ActionResult AddMessage(string message)
{
  Repositories.Shoutbox.ShoutboxRepository repository = new Repositories.Shoutbox.ShoutboxRepository();
  if(string.IsNullOrEmpty(message))
      return PartialView("Messages", repository.GetNewestMessages());

  Entities.ShoutBoxMessage shoutMessage = new Entities.ShoutBoxMessage() { Message = message };
  shoutMessage.ID_MESSAGE = Guid.NewGuid();
  shoutMessage.Date = DateTime.Now;

  if (User.Identity.IsAuthenticated == false)
  {
      if (!string.IsNullOrEmpty(Request["Nick"]))
      {
          shoutMessage.UserName = Request["Nick"];
      }
  }
  else
      shoutMessage.ID_USER = new Guid(System.Web.Security.Membership.GetUser().ProviderUserKey.ToString());

  repository.Create(shoutMessage);
  repository.SubmitChanges();            
  return PartialView("Messages", repository.GetNewestMessages());
}

Kod tworzy wiadomość (klasa ShoutBoxMessage) oraz dodaje ją do baz danych. Następnie akcja zwraca widok “Messages” z zawartością wszystkich wiadomości (repository.GetNewestMessages). Widok częściowy (PartialView) jest dodawany do elementu div (messages) w sposób asynchroniczny. Nie wymaga to oczywiście przeładowania strony. Na zakończenie jeszcze widok Messages.ascx (dodawany do wspomnianego już div):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<PoliticiansPromises.Entities.ShoutBoxMessage>>" %>
<%@ Import Namespace="PoliticiansPromises.Extensions" %>
<% foreach(var item in Model){ %>

<%if(item.ID_USER==null){ 
      
      if(item.UserName==null){
      %>
      <span class="marked_link">~Anonim</span>
      <%}else{ %>
      <span class="marked_link">~<%:item.UserName %></span>
      <%} %>
<%}else{ %>


<span class="marked_link"><%:System.Web.Security.Membership.GetUser(item.ID_USER).UserName %></span>

<%} %>


<span class="small_gray_style"><%: String.Format("{0:g}", item.Date)%></span>
<%=Html.EncodeAndCut(item.Message,500) %>
<br />

<%} %>
<br />

6 thoughts on “ASP.NET MVC – asynchroniczne wysyłanie formularzy (AJAX) na przykładzie prostego ShoutBox’a”

  1. @Darek Tarczyński: a dlaczego nie? Przecież ta metoda jest rzadko wywoływana i po co ciągle przechowywać obiekt repozytorium w pamięci?
    @SirMike: w sumie to szczegół ale teoretycznie ciężko zaprzeczyć – faktycznie nie powinno się tak robić.

  2. @Piotr
    A na jakiej zasadzie twierdzisz, że wywolywana jest rzadko? Rozumiem, że to tylko przykład, ale w systemie produkcyjnym takie stwierdzenie wymagało by przynajmniej specyfikacji przypadków użycia.
    Z drugiej strony wg. mnie akurat ta metoda jest metodą wręcz kluczową w całej aplikacji, gdyż służy do wysyłania wiadomości prawda? Wystarczy, że użytkownicy zaczną pisać wiadomości i odpowadać na nie i już masz niezły ruch.

  3. @Darek Tarczyński
    Ale przeciez repozytorium nie zawiera nic skomplikowanego. Twoim zdaniem powinno to być zaimplementowane za pomocą Singleton’a?

Leave a Reply

Your email address will not be published.