namespace Webzine.WebApplication.Filters;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
///
/// Filtre d'action qui valide automatiquement le ModelState avant l'exécution du contrôleur.
/// Mesure également le temps d'exécution de chaque action (niveau Trace).
///
public class ValidationActionFilter : IActionFilter
{
private readonly ILogger logger;
///
/// Initializes a new instance of the class.
///
/// Service de journalisation injecté.
public ValidationActionFilter(ILogger logger)
{
this.logger = logger;
}
///
public void OnActionExecuting(ActionExecutingContext context)
{
string controllerName = context.RouteData.Values["controller"]?.ToString() ?? string.Empty;
string actionName = context.RouteData.Values["action"]?.ToString() ?? string.Empty;
if (controllerName.Equals("Titre", StringComparison.OrdinalIgnoreCase)
&& actionName.Equals("Comment", StringComparison.OrdinalIgnoreCase))
{
return;
}
if (!context.ModelState.IsValid)
{
var erreurs = context.ModelState
.Where(e => e.Value?.Errors.Count > 0)
.Select(e => $"{e.Key}: {string.Join(", ", e.Value!.Errors.Select(err => err.ErrorMessage))}")
.ToList();
this.logger.LogWarning(
"Validation échouée pour {Action} : {Erreurs}",
context.ActionDescriptor.DisplayName,
string.Join(" | ", erreurs));
// cas spécial: titre details
if (actionName.Equals("Index", StringComparison.OrdinalIgnoreCase))
{
context.Result = new RedirectResult("/");
return;
}
// Récupère le modèle soumis (premier argument de l'action, s'il existe)
object? model = context.ActionArguments.Values.FirstOrDefault();
if (context.Controller is Controller controller)
{
context.Result = new ViewResult
{
ViewName = actionName,
ViewData = new Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary(
controller.ViewData)
{
Model = model,
},
};
}
else
{
context.Result = new BadRequestObjectResult(context.ModelState);
}
}
}
///
public void OnActionExecuted(ActionExecutedContext context)
{
}
}