9.6 Guardando el historial de cambios

Puedes agregar otro action filter para ir registrando todos los cambios que realizan los usuarios al sistema, vamos a registrar el usuario, la fecha en que se realiza el cambio, y un campo adicional para agregar opciones adicionales, como por ejemplo mostrar algún valor anterior.

Agregamos nuestra clase HistorialDAO para registrar el historial de los usuarios. El método borrar va a borrar la información del historial del registro que se esta borrando.

HistorialDAOcs
public class HistorialDAO
{
private readonly CaducaContext contexto;
private readonly LocService localizacion;
public HistorialDAO(CaducaContext context, LocService locService)
{
this.contexto = context;
this.localizacion = locService;
}
public async Task<bool> AgregarAsync(int usuarioId,
int actividad,
string nombreTabla,
int origenId,
string observaciones)
{
var tablaId = await ObtenerIdTablaAsync(nombreTabla);
Historial historial = new Historial
{
Actividad = actividad,
FechaHora = DateTime.Now,
Observa = observaciones,
OrigenId = origenId,
TablaId = tablaId,
UsuarioId = usuarioId
};
contexto.Historial.Add(historial);
contexto.SaveChanges();
return true;
}
private async Task<int> ObtenerIdTablaAsync(string nombreTabla)
{
Tabla tabla = await contexto.Tabla
.FirstOrDefaultAsync(e => e.Nombre == nombreTabla);
if (tabla == null)
{
return -1;
}
return tabla.Id;
}
public async Task<bool> BorraAsync( string nombreTabla,
int origenId)
{
var tablaId = await ObtenerIdTablaAsync(nombreTabla);
var consulta = await (from historial in contexto.Historial
where historial.TablaId == tablaId
&& historial.OrigenId == origenId
select historial).ToListAsync();
contexto.Historial.RemoveRange(consulta);
contexto.SaveChanges();
return true;
}
}

Agregamos una Enumeración ActividadEnumeration con los tipos de actividades que los usuarios pueden realizar.

ActividadEnumeration.cs
public enum ActividadEnumeration
{
Borrar = -1,
Insertar = 1,
Modficar = 2,
Autorizar = 3,
Cancelar = 4
}

Para esto agregamos una propiedad llamada Id de tipo entero a nuestra clase BaseController, aqui vamos a agregar el Id de cada registro que se este actualizando

BaseController.cs
public class BaseController : Controller
{
public int Id;
public string Observaciones;
}

En ProductosController a los métodos Post, Put y Delete vamos a agregar el Id del registro y agregamos nuestro filtro historial

ProductosController.cs
[TypeFilter(typeof(HistorialFilter))]
public class ProductosController : BaseController
{
[HttpPost]
public async Task<IActionResult> PostProducto(
[FromBody] Producto producto)
{
if (!await productoDAO.AgregarAsync(producto))
{
return StatusCode(productoDAO.customError.StatusCode,
productoDAO.customError.Message);
}
Id = producto.Id;
return CreatedAtAction("GetCategoria",
new { id = producto.Id }, producto);
}
[HttpPut("{id}")]
public async Task<IActionResult> PutProducto([FromRoute] int id,
[FromBody] Producto producto)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
if (id != producto.Id)
return BadRequest();
if (!await productoDAO.ModificarAsync(producto))
{
return StatusCode(productoDAO.customError.StatusCode,
productoDAO.customError.Message);
}
Id = producto.Id;
return NoContent();
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteProducto([FromRoute] int id)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
if (!await productoDAO.BorraAsync(id))
{
return StatusCode(productoDAO.customError.StatusCode,
productoDAO.customError.Message);
}
Id = id;
return Ok();
}

En nuestra carpeta Filters agregamos un nueva clase HistorialFilter

HistorialFilter.cs
using System;
using System.Linq;
using System.Security.Claims;
using CaducaRest.Controllers;
using CaducaRest.Core;
using CaducaRest.DAO;
using CaducaRest.Models;
using CaducaRest.Resources;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace CaducaRest.Filters
{
public class HistorialFilter : IActionFilter
{
private readonly LocService _localizer;
private readonly CaducaContext _context;
public HistorialFilter(CaducaContext context,
LocService localizer)
{
this._localizer = localizer;
this._context = context;
}
//Este método se ejecuta al terminar el código de cada
//método
public void OnActionExecuted(ActionExecutedContext context)
{
bool correcto = false;
//Si la acción se realiza correctamente
correcto = context.Result is OkObjectResult
|| context.Result is NoContentResult
|| context.Result is CreatedAtActionResult;
if (correcto)
{
ClaimsPrincipal Usuario = context.HttpContext.User;
//Obtenemos nuestro controlador
var controller = context.Controller as BaseController;
//Obtenemos el método que se ejecutó (POST, PUT,
//DELETE, etc)
string metodo = controller.Request.Method.ToLower();
//Identificamos de acuerdo al método la acción
//realizada
int actividad;
switch (metodo)
{
case "post":
actividad = (int)ActividadEnumeration.Insertar;
break;
case "put":
case "patch":
actividad = (int)ActividadEnumeration.Modficar;
break;
case "delete":
actividad = (int)ActividadEnumeration.Borrar;
break;
default:
actividad = 0;
break;
}
int UsuarioId = 0;
if (correcto)
{
int.TryParse(Usuario.Claims
.FirstOrDefault(x => x.Type == ClaimTypes.Sid)
.Value, out UsuarioId);
if (UsuarioId > 0 && controller.Id > 0)
{
//Si es una acción de alta o edición
//agregamos un registro al historial
HistorialDAO historialDAO =
new HistorialDAO(_context, _localizer);
if (actividad > 0)
_ = historialDAO.AgregarAsync(UsuarioId,
actividad,
controller.permiso.Tabla,
controller.Id,
controller.Observaciones).Result;
else
{
//Borramos el historial del registro
if (actividad < 0)
_ = historialDAO
.BorraAsync(controller.permiso.Tabla,
controller.Id).Result;
}
}
}
}
}
public void OnActionExecuting(ActionExecutingContext context)
{
}
}
}

De esta manera cada vez que se guarda, modifica, o borra algún registro guardamos el historial de cambios del registro.