AJAX fácil con @Ajax.ActionLink en ASP.NET MVC 5
Trabajar con AJAX en nuestros desarrollos ASP.NET MVC, puede ser a veces una tarea algo complicada, sobre todo para los desarrolladores que no somos del todo expertos en FrontEnd y JavaScript.
Afortunadamente, el Framework ASP.NET MVC 5, nos proporciona una forma eficiente y transparente para el desarrollador de integrar AJAX en nuestras aplicaciones, mediante el uso de los llamados Ajax Helpers, y mas en concreto el Helper @Ajax.ActionLink().
En este artículo veremos cómo solicitar desde una Vista y de manera asíncrona datos al servidor, para posteriormente ser actualizados en la misma página vía AJAX.
Creando el proyecto
Para este ejemplo, utilizaremos Visual Studio 2019 para crear un nuevo proyecto Web ASP.NET MVC, con plataforma de destino .NET Framework 4.6.1 (>= 4.5).
La aplicación de ejemplo consistirá en un sencillo sistema de Blog, donde mostraremos a través de un Link todos los títulos de los Posts creados, de tal manera que al hacer click sobre alguno de ellos, se actualice en pantalla la información completa del Post.
Nota: Todo este proceso lo haremos sin enviar en ningún momento la página completa al Servidor, o sea, mediante AJAX enviaremos solo los datos y recibiremos solo la información necesaria para actualizar parcialmente la página.
El Modelo de datos
En primer lugar crearemos la clase Post.cs
que será el Modelo de datos principal de la aplicación.
public class Post
{
public Post()
{
this.Id = Guid.NewGuid();
this.Fecha = DateTime.Now;
}
[Required]
[Key]
public Guid Id { get; set; }
[Required]
public DateTime Fecha { get; set; }
[StringLength(50)]
[Required(ErrorMessage ="Este campo es obligatorio.")]
[RegularExpression(@"^[A-Z a-z0-9ÑñáéíóúÁÉÍÓÚ\\-\\_]+$",
ErrorMessage = "El Nombre debe ser alfanumérico.")]
[Display(Name = "Nombre")]
public string Nombre { get; set; }
[RegularExpression(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*",
ErrorMessage = "Dirección de Correo electrónico incorrecta.")]
[StringLength(50)]
[Display(Name = "Correo electrónico")]
public string Email { get; set; }
[StringLength(100)]
[Required(ErrorMessage = "Este campo es obligatorio.")]
[Display(Name = "Título")]
public string Titulo { get; set; }
[StringLength(1500)]
[Required(ErrorMessage = "Este campo es obligatorio.")]
[DataType(DataType.MultilineText)]
[Display(Name = "Comentario")]
public string Comentario { get; set; }
}
También crearemos la clase auxiliar TituloPostViewModel.cs
, que contendrá los datos del Modelo (ViewModel) que posteriormente serán enviados a la Vista principal de la aplicación. Este ViewModel sólo contendrá el Id
, la Fecha
y el Título
del Post.
public class TituloPostViewModel
{
public Guid Id { get; set; }
public DateTime Fecha { get; set; }
public string Titulo { get; set; }
}
El Controlador
A continuación crearemos el Controlador HomeController.cs
, el cual contendrá dos Acciones.
La Acción Index()
, será la encargada de recuperar los títulos de los Posts y enviarlos a la Vista mediante una Lista del ViewModel TituloPostViewModel.cs
.
La Acción GetPostDetalle(Guid id)
, se encargará de recuperar los detalles de un determinado Post, y enviarlo a través de la Vista parcial _PostDetalle.cshtml
.
public class HomeController : Controller
{
private ApplicationDbContext _dbContext;
// ACCIÓN POR DEFECTO, DEVUELVE A LA VISTA UNA LISTA DE POSTS
public ActionResult Index()
{
using (_dbContext = new ApplicationDbContext())
{
var postsList = _dbContext.Posts.Select(x => new TituloPostViewModel
{
Id = x.Id,
Fecha = x.Fecha,
Titulo = x.Titulo
}).OrderByDescending(x => x.Fecha).ToList();
return View(postsList);
}
}
// ACCIÓN QUE SERÁ LLAMADA VIA AJAX DESDE EL @Ajax.ActionLink()
// DEVUELVE UNA VISTA PARCIAL CON LOS DATOS DEL POST SELECCIONADO.
public PartialViewResult GetPostDetalle (Guid id)
{
using (_dbContext = new ApplicationDbContext())
{
var postDetalle = _dbContext.Posts.Where(x => x.Id == id).FirstOrDefault();
return PartialView("_PostDetalle", postDetalle);
}
}
}
Nota: Como podemos ver, el Controlador hace referencia a un objeto privado del tipo
ApplicationDbContext
(Contexto de datos de Entity Framework). Para más información acerca de cómo implementar unDbContext
de Entity Framework en ASP.NET MVC, pueden consultar el siguiente Post: Entity Framework 6 y Sql Server Compact CE en ASP.NET MVC 5.
La Vista
Antes de implementar la Vista principal de la aplicación, crearemos la Vista parcial _PostListPartial.cshtml
. Está se encargará de construir el detalle del Post seleccionado, a través de la clase Post
.
@model Post
<div class="row">
<div class="col-md-12">
<div>
<strong>
@Model.Fecha.ToShortDateString()
@Model.Fecha.ToLongTimeString()
</strong>
<span>@Model.Nombre</span>
<span>@Model.Email</span>
</div>
<strong>@Model.Titulo</strong>
<p>
@Model.Comentario
</p>
<hr />
</div>
</div>
Ahora ya podemos crear la Vista principal de la aplicación Index.cshtml
. Esta es realmente la parte más importante de nuestra aplicación de ejemplo, ya que es aquí donde implementaremos el Ajax Helper @Ajax.ActionLink()
, el cual se encargará de hacer las llamadas asíncronas (AJAX) al Servidor para recuperar los datos solicitados.
El Ajax Helper @Ajax.ActionLink()
Antes de ver cómo crear la Vista principal, analizaremos brevemente el funcionamiento del Ajax Helper @Ajax.ActionLink()
.
Una plantilla estándar de este Helper, sería la siguiente:
@Ajax.ActionLink("Titulo del Link",
"GetPostDetalle",
"Home",
new { id = Value }, // Route Values.
new AjaxOptions()
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "PostDetalle",
OnBegin = "onBeginAjax",
OnComplete = "onCompleteAjax",
OnSuccess = "onSuccessAjax",
OnFailure = "onFailureAjax"
},
new { id = "IdLink", @class = "miClaseCss" })
Como vemos, @Ajax.ActionLink()
recibe como parámetro un objeto del tipo AjaxOptions
, en el cual configuraremos a través de sus propiedades el comportamiento AJAX que tendrá el control.
Si observáramos el código fuente HTML que genera este Ajax Helper, veríamos que se ha generado una etiqueta del tipo anchor <a />
, con una serie de atributos del tipo data-ajax-....=
.
<a class="miClaseCss"
data-ajax="true"
data-ajax-begin="onBeginAjax"
data-ajax-complete="onCompleteAjax"
data-ajax-failure="onFailureAjax"
data-ajax-method="GET"
data-ajax-mode="replace"
data-ajax-success="onSuccessAjax"
data-ajax-update="#PostDetalle"
href="/Home/GetPostDetalle/69c9ec93-2929-404a-9050-3d66e6194f06"
id="IdLink">
Titulo del Link
</a>
Esto es debido a que el Helper @Ajax.ActionLink()
, solo funciona en conjunción a la librería jQuery jquery.unobtrusive-ajax.js
, la cual será la encargada de interpretar los atributos data-ajax-....=
del anchor <a />
para darle la funcionalidad AJAX requerida.
Instalando jQuery unobtrusive Ajax
Desde la consola de administración de paquetes NuGet (Herramientas > Administrador de paquetes NuGet > Consola del Administrador de paquetes), ejecutaremos el siguiente comando:
PM> Install-Package Microsoft.jQuery.Unobtrusive.Ajax
Una vez finalizada la instalación, comprobaremos que en la carpeta Scripts de nuestro proyecto se han creado correctamente los Scripts jquery.unobtrusive.ajax*
.
En los proyectos ASP.NET MVC 5, los Scripts que posteriormente insertaremos en nuestras Vistas, deben ser definidos con anterioridad en el archivo de configuración BundleConfig.cs
, dentro de la carpeta App_Start
.
Siguiendo esta convención, añadiremos el siguiente código a la clase BundleConfig.cs
:
public class BundleConfig
{
// Para obtener más información sobre las uniones, visite
// https://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
// ...
// JQUERY UNOBTRUSIVE PARA @Ajax.ActionLink()
bundles.Add(new ScriptBundle("~/bundles/jqueryajax").Include(
"~/Scripts/jquery.unobtrusive*"));
// ...
}
}
Posteriormente, en nuestra Vista principal, "renderizaremos" estos Scripts dentro de la sección @section scripts {...}
de la siguiente manera:
@section scripts {
// ...
@*JQUERY UNOBTRUSIVE PARA Ajax.ActionLink()*@
@Scripts.Render("~/bundles/jqueryajax")
// ...
}
La Vista principal
Llegados a este punto, ya podemos crear la Vista Index.cshtml
. El código sería el siguiente:
@model List<TituloPostViewModel>
<h3>PostList</h3>
<div class="row">
@foreach (var item in Model)
{
<div class="col-md-10">
<br />
@item.Fecha.ToShortDateString()
<strong>
@Ajax.ActionLink(item.Titulo,
"GetPostDetalle",
"Home",
new { id = item.Id.ToString() },
new AjaxOptions()
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "PostDetalle",
OnBegin = "onBeginAjax",
OnComplete = "onCompleteAjax",
OnSuccess = "onSuccessAjax",
OnFailure = "onFailureAjax"
},
new { id = "IdLink", @class = "miClaseCss" })
</strong>
</div>
}
</div>
<hr />
<h3>BlogPost</h3>
<br />
@* ELEMENTO DONDE SE INSERTARÁ EL RESULTADO HTML
DE LA VISTA PARCIAL _PostDetalle.cshtml *@
<div class="" id="PostDetalle">
</div>
@section scripts {
<!-- JQUERY UNOBTRUSIVE PARA Ajax.ActionLink() -->
@Scripts.Render("~/bundles/jqueryajax")
<!-- AL COMENZAR LA LLAMADA AJAX -->
<script>
var onBeginAjax = function () {
alert("Begin");
};
</script>
<!-- AL FINALIZAR LA LLAMADA AJAX -->
<script>
var onCompleteAjax = function () {
alert("Complete");
};
</script>
<!-- SE EJECUTA SI TODO FUE BIEN -->
<script>
var onSuccessAjax = function () {
alert("Success");
};
</script>
<!-- SE EJECUTA SI TODO FUE BIEN -->
<script>
var onFailureAjax = function () {
alert("Failure");
};
</script>
}
La Librería jQuery
Si observamos el código de la Vista Index.cshtml
, nos daremos cuenta de que no hemos hecho referencia en ningún momento a la librería JavaScript principal de jQuery (jquery-x.x.x.min.js
). Esto se debe a que Visual Studio la incluye en la página maestra o Layout (_Layout.cshtml
) cuando creamos un nuevo proyecto web ASP.NET MVC.
Nota: También incluye por defecto en la página maestra (Layout) las librerías Bootstrap, hojas de estilo y JavaScripts de la aplicación.
Nuevo comentario
Comentarios
No hay comentarios para este Post.