![]() | por Gisela Torres Senior Developer en Alten España |
Cuando creamos un proyecto de MVC, de forma automática se genera una carpeta llamada Scripts con los siguientes archivos js:
.jpg)
En el momento que queramos hacer uso de ellos, únicamente debemos importarlos, generalmente en la Master Page de nuestra aplicación:
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>
<asp:ContentPlaceHolder ID="TitleContent" runat="server"/>
</title>
<link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
<script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="../../Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="../../Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
</head>
Para mostrar un ejemplo de la forma de trabajar con Ajax en una aplicación MVC, voy a llevar a cabo una serie de pasos para ajustar el contenido de la aplicación Movie Manager usada en otros ejemplos.
PARTIAL VIEW DEL LISTADO DE PELÍCULAS
Seleccionamos la carpeta Movie, dentro de Views, y con lo el botón derecho seleccionamos Add => View. Especificamos la siguiente configuración:
.jpg)
Pulsando en Add, se genera una nueva vista con extensión ascx. He modificado ligeramente el contenido para configurar las acciones de detalle, edición y una última para la eliminación de películas de manera asíncrona con Ajax. Además, he añadido tres funciones utilizando JQuery.
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<MovieManager.Models.Objects.Movie>>" %>
<%@ Import Namespace="MovieManager.Helpers" %>
<script type="text/javascript">
function beginMovieList(args) {
$('#divMovieList').slideUp('normal');
}
function successMovieList() {
$('#divMovieList').slideDown('normal');
}
function failureMovieList() {
alert("Could not retrieve movies.");
}
</script>
<table>
<tr>
<th>
</th>
<th>
Id
</th>
<th>
Name
</th>
<th>
Genre
</th>
<th>
Synopsis
</th>
<th>
Date
</th>
</tr>
<% foreach (var item in Model)
{ %>
<tr>
<td>
<%=Html.ImageLink("Movie", "Details", "Content\\detail.gif", new {item.Id })%>
|
<%=Html.ImageLink("Movie","Edit","Content\\edit.gif",new {item.Id }) %>
|
<%= Ajax.ActionLink("Delete", "Delete", new { id = item.Id }, new AjaxOptions { Confirm = "Delete movie?", HttpMethod = "Delete", UpdateTargetId = "divMovieList", OnBegin = "beginMovieList", OnComplete = "successMovieList", OnFailure = "failureMovieList" })%>
</td>
<td>
<%= Html.Encode(item.Id) %>
</td>
<td>
<%= Html.Encode(item.Name) %>
</td>
<td>
<%= Html.Encode(item.Genre) %>
</td>
<td>
<%= Html.Encode(item.Synopsis) %>
</td>
<td>
<%= Html.Encode(String.Format("{0:g}", item.Date)) %>
</td>
</tr>
<% } %>
</table>
En la acción Delete se ha utilizado el helper específico para los controles Ajax. Dentro del mismo, he usado ActionLink donde se usan los mismos parámetros que en un control normal del Html helper a excepción del último parámetro: AjaxOptions. Este objeto, contiene una serie de propiedades para su configuración. Las utilizadas en el ejemplo son:
MODIFICAR LA VISTA INDEX
Para poder hacer uso de la partial view, y no perder la funcionalidad hasta ahora conseguida, debemos modificar la vista Movies/Index.aspx de la siguiente manera:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MovieManager.Models.Objects.Movie>>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Index
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>
Index</h2>
<div id="divMovieList">
<% Html.RenderPartial("MovieList"); %>
</div>
<p>
<%= Html.ActionLink("Create New", "Create") %>
</p>
</asp:Content>
Se ha añadido un elemento de tipo div, el cual contiene una llamada a Html.RenderPartial que renderizará la vista parcial que acabamos de crear.
En MovieController creamos una nueva acción para eliminar la película seleccionada.
[AcceptVerbs(HttpVerbs.Delete)]
public ActionResult Delete(int id)
{
var movieToDelete = _movieRepository.GetMovie(id);
_movieRepository.Delete(movieToDelete);
returnPartialView("MovieList", _movieRepository.ListMovies());
}
Cuando recupera la película a través de NHibernate y elimina la misma, retorna el nuevo listado de películas a MovieList.
Los métodos Delete y GetMovie han sido añadidos tanto en la interfaz IMovieRepository como en su implementación, siempre en la parte del Modelo.
using System.Collections.Generic;
using MovieManager.Models.Objects;
namespace MovieManager.Models
{
public interface IMovieRepository
{
IList<Movie> ListMovies();
voidSaveMovie(Movie movieToSave);
Movie GetMovie(intid);
voidDelete(Movie movieToDelete);
}
}using System.Collections.Generic;
using MovieManager.Models.Objects;
using NHibernate;
using NHibernate.Criterion;
namespace MovieManager.Models
{
public class MovieRepository : IMovieRepository
{
private readonly ISessionFactory _session;
publicMovieRepository(ISessionFactory sessionFactory)
{
_session = sessionFactory;
}
publicIList<Movie> ListMovies()
{
return_session.GetCurrentSession().CreateCriteria(typeof(Movie)).List<Movie>();
}
public void SaveMovie(Movie movieToSave)
{
_session.GetCurrentSession().SaveOrUpdate(movieToSave);
}
public Movie GetMovie(int id)
{
return(Movie)_session.GetCurrentSession().CreateCriteria(typeof(Movie))
.Add(Restrictions.Like("Id", id)).UniqueResult();
}
publicvoidDelete(Movie movieToDelete)
{
_session.GetCurrentSession().Delete(movieToDelete);
}
}
}
Como hemos visto, podemos trabajar de una forma más simplificada con Ajax, gracias a MVC y JQuery, adaptando la aplicación de una forma poco agresiva :)
Adjunto el proyecto por si fuera de utilidad.