Ajax en ASP.NET Core MVC: Notificaciones en Tiempo Real con jQuery
Las notificaciones en tiempo real mejoran significativamente la experiencia del usuario al proporcionar actualizaciones instantáneas sin necesidad de recargar la página. En este artículo, explicaremos cómo implementar notificaciones en tiempo real utilizando Ajax en una aplicación ASP.NET Core.
Introducción a las Notificaciones en Tiempo Real
Las notificaciones en tiempo real permiten a los usuarios recibir actualizaciones instantáneas, como mensajes nuevos, alertas o cualquier tipo de información relevante, sin tener que refrescar la página. Utilizando Ajax con jQuery, podemos realizar solicitudes periódicas al servidor para comprobar la existencia de nuevas notificaciones y mostrarlas en la interfaz del usuario.
Configuración del Proyecto ASP.NET Core
Para empezar, necesitamos un proyecto ASP.NET Core configurado. Si aún no tienes uno, sigue estos pasos para crear uno nuevo en Visual Studio:
- Abre Visual Studio y selecciona "Crear un nuevo proyecto".
- Elige "Aplicación web ASP.NET Core" y haz clic en "Siguiente".
- Configura el proyecto y asegúrate de seleccionar ".NET 5.0" o superior.
- Selecciona la plantilla "Aplicación Web (Modelo-Vista-Controlador)" y crea el proyecto.
Una vez creado el proyecto, vamos a incluir jQuery para manejar las solicitudes Ajax. Añade la referencia a jQuery en el archivo _Layout.cshtml
:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>@ViewData["Title"] - My ASP.NET Core Application</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<div class="container">
@RenderBody()
</div>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Implementación del Controlador
Primero, necesitamos un controlador que maneje las solicitudes para comprobar y enviar notificaciones. Vamos a crear un controlador llamado NotificationsController
.
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class NotificationsController : Controller
{
private static readonly List<string> Notifications = new List<string>
{
"You have a new message from John.",
"Your order has been shipped.",
"You have a new friend request."
};
[HttpGet]
public IActionResult GetLatestNotification()
{
if (Notifications.Count > 0)
{
var latestNotification = Notifications.Last();
Notifications.RemoveAt(Notifications.Count - 1);
return Json(new { success = true, message = latestNotification });
}
return Json(new { success = false, message = "No new notifications." });
}
}
En este código:
- Creamos una lista estática de notificaciones para simular datos.
- El método
GetLatestNotification
devuelve la notificación más reciente y la elimina de la lista.
Creación de la Vista
Ahora crearemos una vista llamada Index.cshtml
en la carpeta Views/Home
. Esta vista incluirá un contenedor para mostrar las notificaciones y un script para realizar solicitudes Ajax periódicas al servidor.
@{
ViewData["Title"] = "Home Page";
}
<div class="container">
<h2>Notifications</h2>
<div id="notifications">
<!-- Notificaciones aparecerán aquí -->
</div>
</div>
@section Scripts {
<script>
$(document).ready(function () {
function checkForNotifications() {
$.ajax({
url: '/Notifications/GetLatestNotification',
type: 'GET',
success: function (response) {
if (response.success) {
$('#notifications').prepend('<p>' + response.message + '</p>');
}
},
error: function () {
console.log('Error while checking for notifications.');
}
});
}
// Check for notifications every 5 seconds
setInterval(checkForNotifications, 5000);
});
</script>
}
En este código:
- Utilizamos
setInterval
para ejecutar la funcióncheckForNotifications
cada 5 segundos. - La función
checkForNotifications
realiza una solicitud Ajax al controladorNotificationsController
para obtener la notificación más reciente. - Si hay una nueva notificación, se añade al principio del contenedor
#notifications
.
Uso de jQuery y Ajax para Solicitudes en Tiempo Real
Para implementar notificaciones en tiempo real, utilizaremos jQuery y Ajax para realizar solicitudes periódicas al servidor y verificar la existencia de nuevas notificaciones.
Implementación del Script jQuery
Dentro de la vista Index.cshtml
, vamos a desarrollar el script jQuery que manejará la lógica de solicitudes Ajax y actualización de la interfaz de usuario con nuevas notificaciones.
@section Scripts {
<script>
$(document).ready(function () {
// Función para realizar la solicitud de notificaciones
function checkForNotifications() {
$.ajax({
url: '/Notifications/GetLatestNotification', // URL del controlador y acción que devuelve la última notificación
type: 'GET', // Tipo de solicitud GET
success: function (response) { // Función que se ejecuta si la solicitud tiene éxito
if (response.success) { // Verificar si la solicitud fue exitosa
// Agregar la nueva notificación al principio de la lista de notificaciones
$('#notifications').prepend('<p>' + response.message + '</p>');
}
},
error: function () { // Función que se ejecuta si hay un error en la solicitud
console.log('Error al verificar las notificaciones.');
}
});
}
// Llamar a la función checkForNotifications cada 5 segundos
setInterval(checkForNotifications, 5000); // Realiza la comprobación cada 5 segundos (5000 milisegundos)
});
</script>
}
Explicación del Código jQuery
-
$(document).ready(function () { ... }): Esta función asegura que el DOM esté completamente cargado antes de ejecutar cualquier código jQuery. Es fundamental para garantizar que todos los elementos HTML estén disponibles para interactuar con ellos.
-
$.ajax: Utilizamos este método de jQuery para realizar una solicitud Ajax. En este caso, configuramos la URL de la solicitud (
url
) para apuntar a la acciónGetLatestNotification
en el controladorNotificationsController
que hemos creado previamente. -
type: 'GET': Especificamos que queremos hacer una solicitud GET al servidor para obtener la última notificación. Esto es adecuado ya que estamos simplemente obteniendo datos del servidor sin realizar cambios.
-
success: Este es el manejador de éxito de la solicitud Ajax. Si la solicitud se realiza correctamente y se recibe una respuesta del servidor, esta función se ejecutará. En nuestro caso, verificamos si
response.success
estrue
, lo que indica que hay una nueva notificación disponible. -
$('#notifications').prepend('<p>' + response.message + '</p>');: Utilizamos
prepend
para agregar dinámicamente el mensaje de la notificación al principio del contenedor#notifications
en nuestra vista. Esto asegura que las notificaciones más recientes aparezcan primero. -
error: En caso de que haya un problema al realizar la solicitud Ajax (por ejemplo, el servidor no responde o hay un error en el código del servidor), esta función manejará el error y mostrará un mensaje en la consola del navegador para depuración.
Actualización Periódica de Notificaciones
- setInterval(checkForNotifications, 5000);: Utilizamos
setInterval
para llamar a la funcióncheckForNotifications
cada 5 segundos (5000 milisegundos). Esto asegura que nuestro cliente revise continuamente si hay nuevas notificaciones en el servidor sin requerir ninguna acción del usuario.
Nota: Este enfoque de "polling" es común para las notificaciones en tiempo real cuando no se utiliza WebSocket u otro protocolo de conexión persistente.
Optimización y Buenas Prácticas
Implementar notificaciones en tiempo real de manera eficiente y escalable requiere seguir ciertas optimizaciones y buenas prácticas. Aquí abordaremos cómo aplicar persistencia de datos y personalización de notificaciones para mejorar nuestra implementación.
Persistencia de Datos
Guardar las notificaciones en una base de datos permite mantener un registro persistente y accesible de todas las notificaciones, lo cual es fundamental para la recuperación de datos en caso de fallos del sistema o para proporcionar historial a los usuarios.
1. Configurar Entity Framework Core:
Primero, asegurémonos de que nuestro proyecto esté configurado para usar Entity Framework Core.
Instala los paquetes necesarios de NuGet:
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
Configura el contexto de la base de datos:
using Microsoft.EntityFrameworkCore;
namespace RealTimeNotifications.Data
{
public class NotificationContext : DbContext
{
public NotificationContext(DbContextOptions<NotificationContext> options) : base(options) { }
public DbSet<Notification> Notifications { get; set; }
}
public class Notification
{
public int Id { get; set; }
public string Title { get; set; }
public string Message { get; set; }
public DateTime DateCreated { get; set; }
public string UserId { get; set; } // Agregar usuario para personalización
}
}
Configura el servicio de DbContext en Startup.cs
:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<NotificationContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddControllersWithViews();
}
Crea la base de datos y las tablas ejecutando las migraciones:
dotnet ef migrations add InitialCreate
dotnet ef database update
2. Actualizar el Controlador:
Modificaremos nuestro NotificationController
para usar Entity Framework Core y guardar las notificaciones en la base de datos.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Identity;
using RealTimeNotifications.Data;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace RealTimeNotifications.Controllers
{
public class NotificationController : Controller
{
private readonly NotificationContext _context;
private readonly UserManager<IdentityUser> _userManager;
public NotificationController(NotificationContext context, UserManager<IdentityUser> userManager)
{
_context = context;
_userManager = userManager;
}
public IActionResult Index()
{
return View();
}
[HttpGet]
public IActionResult GetNotifications()
{
var userId = _userManager.GetUserId(User); // Obtener el ID del usuario autenticado
var notifications = _context.Notifications
.Where(n => n.UserId == userId)
.OrderByDescending(n => n.DateCreated)
.Take(10)
.ToList();
return Json(notifications);
}
[HttpPost]
public async Task<IActionResult> CreateNotification([FromBody] Notification notification)
{
if (notification == null)
{
return BadRequest(new { success = false, message = "Datos de notificación inválidos." });
}
notification.DateCreated = DateTime.Now;
notification.UserId = _userManager.GetUserId(User); // Asignar el ID del usuario autenticado
_context.Notifications.Add(notification);
await _context.SaveChangesAsync();
return Ok(new { success = true, message = "Notificación creada exitosamente." });
}
}
}
3. Actualizar la Vista Index.cshtml:
Actualizaremos nuestra vista para permitir la creación de notificaciones y mostrar una lista de notificaciones personalizadas basadas en el usuario autenticado.
@model IEnumerable<RealTimeNotifications.Data.Notification>
@{
ViewData["Title"] = "Notificaciones en Tiempo Real";
}
<h2>Notificaciones en Tiempo Real</h2>
<div>
<input type="text" id="notificationTitle" placeholder="Título" required />
<input type="text" id="notificationMessage" placeholder="Mensaje" required />
<button id="createNotification">Crear Notificación</button>
</div>
<div id="notificationArea">
<!-- Las notificaciones se cargarán aquí -->
@foreach (var notification in Model)
{
<p>@notification.Title: @notification.Message (@notification.DateCreated.ToString("dd/MM/yyyy HH:mm:ss"))</p>
}
</div>
<button id="loadNotifications">Cargar Notificaciones</button>
@section Scripts {
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#loadNotifications').click(function () {
loadNotifications();
});
$('#createNotification').click(function () {
var title = $('#notificationTitle').val();
var message = $('#notificationMessage').val();
createNotification(title, message);
});
function loadNotifications() {
$.ajax({
url: '/Notification/GetNotifications',
type: 'GET',
success: function (notifications) {
$('#notificationArea').empty();
if (notifications.length > 0) {
notifications.forEach(function (notification) {
$('#notificationArea').append('<p>' + notification.Title + ': ' + notification.Message + ' (' + new Date(notification.DateCreated).toLocaleString() + ')</p>');
});
} else {
$('#notificationArea').append('<p>No hay nuevas notificaciones.</p>');
}
},
error: function () {
$('#notificationArea').append('<p>Ocurrió un error al cargar las notificaciones.</p>');
}
});
}
function createNotification(title, message) {
$.ajax({
url: '/Notification/CreateNotification',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ Title: title, Message: message }),
success: function (response) {
if (response.success) {
alert(response.message);
loadNotifications();
} else {
alert('Error: ' + response.message);
}
},
error: function () {
alert('Ocurrió un error al crear la notificación.');
}
});
}
// Llamar a la función loadNotifications periódicamente para simular notificaciones en tiempo real
setInterval(loadNotifications, 5000);
});
</script>
}
En esta vista, hemos actualizado el bucle foreach
para mostrar las notificaciones personalizadas basadas en el usuario autenticado, utilizando el modelo Notification
que contiene el título, el mensaje y la fecha de creación de cada notificación.
Personalización de Notificaciones
La personalización de notificaciones implica mostrar únicamente aquellas que sean relevantes para cada usuario, basado en criterios como sus intereses, configuraciones de cuenta o roles en la aplicación. En este ejemplo, utilizaremos la información del usuario autenticado para filtrar y mostrar solo las notificaciones pertinentes.
1. Actualizar el Controlador:
Modificaremos nuestro NotificationController
para incorporar la personalización de notificaciones basada en el usuario autenticado.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Identity;
using RealTimeNotifications.Data;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace RealTimeNotifications.Controllers
{
public class NotificationController : Controller
{
private readonly NotificationContext _context;
private readonly UserManager<IdentityUser> _userManager;
public NotificationController(NotificationContext context, UserManager<IdentityUser> userManager)
{
_context = context;
_userManager = userManager;
}
public IActionResult Index()
{
return View();
}
[HttpGet]
public IActionResult GetNotifications()
{
var userId = _userManager.GetUserId(User); // Obtener el ID del usuario autenticado
var notifications = _context.Notifications
.Where(n => n.UserId == userId && n.IsRead == false) // Filtrar notificaciones no leídas del usuario
.OrderByDescending(n => n.DateCreated)
.Take(10)
.ToList();
return Json(notifications);
}
[HttpPost]
public async Task<IActionResult> CreateNotification([FromBody] Notification notification)
{
if (notification == null)
{
return BadRequest(new { success = false, message = "Datos de notificación inválidos." });
}
notification.DateCreated = DateTime.Now;
notification.UserId = _userManager.GetUserId(User); // Asignar el ID del usuario autenticado
_context.Notifications.Add(notification);
await _context.SaveChangesAsync();
return Ok(new { success = true, message = "Notificación creada exitosamente." });
}
}
}
En este controlador, hemos modificado el método GetNotifications
para filtrar las notificaciones basadas en el UserId
del usuario autenticado y solo mostrar las que aún no han sido marcadas como leídas (IsRead == false
).
2. Actualizar la Vista Index.cshtml:
Actualizaremos nuestra vista para mostrar solo las notificaciones relevantes para el usuario autenticado.
@model IEnumerable<RealTimeNotifications.Data.Notification>
@{
ViewData["Title"] = "Notificaciones en Tiempo Real";
}
<h2>Notificaciones en Tiempo Real</h2>
<div id="notificationArea">
<!-- Las notificaciones se cargarán aquí -->
@foreach (var notification in Model)
{
<p>@notification.Title: @notification.Message (@notification.DateCreated.ToString("dd/MM/yyyy HH:mm:ss"))</p>
}
</div>
<button id="loadNotifications">Cargar Notificaciones</button>
@section Scripts {
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#loadNotifications').click(function () {
loadNotifications();
});
function loadNotifications() {
$.ajax({
url: '/Notification/GetNotifications',
type: 'GET',
success: function (notifications) {
$('#notificationArea').empty();
if (notifications.length > 0) {
notifications.forEach(function (notification) {
$('#notificationArea').append('<p>' + notification.Title + ': ' + notification.Message + ' (' + new Date(notification.DateCreated).toLocaleString() + ')</p>');
});
} else {
$('#notificationArea').append('<p>No hay nuevas notificaciones.</p>');
}
},
error: function () {
$('#notificationArea').append('<p>Ocurrió un error al cargar las notificaciones.</p>');
}
});
}
// Llamar a la función loadNotifications periódicamente para simular notificaciones en tiempo real
setInterval(loadNotifications, 5000);
});
</script>
}
En esta vista, hemos eliminado el botón de creación de notificaciones y el input para el título y mensaje, ya que en este caso estamos enfocándonos únicamente en mostrar las notificaciones personalizadas basadas en el usuario autenticado.
Conclusiones
En este artículo, hemos explorado cómo implementar notificaciones en tiempo real utilizando Ajax en una aplicación ASP.NET Core. Hemos cubierto desde la configuración inicial del proyecto hasta la implementación del controlador y la vista para mostrar las notificaciones dinámicamente.
Implementar notificaciones en tiempo real mejora significativamente la experiencia del usuario al proporcionar actualizaciones instantáneas sin interrupciones. Puedes expandir esta funcionalidad agregando más lógica de negocio, como persistencia de datos y personalización de notificaciones.
Nuevo comentario
Comentarios
No hay comentarios para este Post.