diff --git a/Webzine.Business/Webzine.Business.csproj b/Webzine.Business/Webzine.Business.csproj index 8328d31..1142cdb 100644 --- a/Webzine.Business/Webzine.Business.csproj +++ b/Webzine.Business/Webzine.Business.csproj @@ -26,12 +26,7 @@ - - - - - ..\..\..\..\..\..\..\.nuget\packages\microsoft.extensions.logging.abstractions\10.0.5\lib\net10.0\Microsoft.Extensions.Logging.Abstractions.dll - + diff --git a/Webzine.Repository/DbStyleRepository.cs b/Webzine.Repository/DbStyleRepository.cs index 8cb5120..d831ead 100644 --- a/Webzine.Repository/DbStyleRepository.cs +++ b/Webzine.Repository/DbStyleRepository.cs @@ -94,7 +94,6 @@ public class DbStyleRepository : IStyleRepository this.logger.LogDebug("Recherche du style avec l'ID: {Id}", id); var style = this.context.Styles - .AsNoTracking() .Include(s => s.Titres) .SingleOrDefault(s => s.IdStyle == id); @@ -123,7 +122,6 @@ public class DbStyleRepository : IStyleRepository this.logger.LogDebug("Tri des styles par libellé"); var styles = this.context.Styles - .AsNoTracking() .OrderBy(s => s.Libelle); this.logger.LogDebug("La liste de styles a été récupérée."); diff --git a/Webzine.WebApplication/Areas/Administration/Controllers/ArtisteController.cs b/Webzine.WebApplication/Areas/Administration/Controllers/ArtisteController.cs index a58d51a..c5df960 100644 --- a/Webzine.WebApplication/Areas/Administration/Controllers/ArtisteController.cs +++ b/Webzine.WebApplication/Areas/Administration/Controllers/ArtisteController.cs @@ -74,14 +74,6 @@ public class ArtisteController : Controller [HttpPost] public IActionResult Create(ArtisteCreateViewModel model) { - // vérifier si les données sont corrects. - if (!this.ModelState.IsValid) - { - // Passer model en paramètre afin que - // l'utilisateur conserve sa saissie. - return this.View(model); - } - // Créer un objet Artiste avecc les paramètres. var artiste = new Artiste { @@ -121,18 +113,16 @@ public class ArtisteController : Controller [HttpPost] public IActionResult Edit(ArtisteEditViewModel model) { - var artiste = new Artiste - { - IdArtiste = model.Id, - Nom = model.Nom, - Biographie = model.Biographie, - }; + var artiste = this.artisteRepository.Find(model.Id); - if (!this.ModelState.IsValid) + if (artiste == null) { - return this.View(artiste); + return this.RedirectToAction("Index"); } + artiste.Nom = model.Nom; + artiste.Biographie = model.Biographie; + this.artisteRepository.Update(artiste); return this.RedirectToAction("Index"); diff --git a/Webzine.WebApplication/Areas/Administration/Controllers/CommentaireController.cs b/Webzine.WebApplication/Areas/Administration/Controllers/CommentaireController.cs index 4556ad3..008d69a 100644 --- a/Webzine.WebApplication/Areas/Administration/Controllers/CommentaireController.cs +++ b/Webzine.WebApplication/Areas/Administration/Controllers/CommentaireController.cs @@ -96,11 +96,6 @@ namespace Webzine.WebApplication.Areas.Administration.Controllers { var commentaire = this.commentaireRepository.Find(model.IdCommentaire); - if (!this.ModelState.IsValid) - { - return this.View(commentaire); - } - if (commentaire != null) { this.commentaireRepository.Delete(commentaire); diff --git a/Webzine.WebApplication/Areas/Administration/Controllers/DashboardController.cs b/Webzine.WebApplication/Areas/Administration/Controllers/DashboardController.cs index a882a68..560533e 100644 --- a/Webzine.WebApplication/Areas/Administration/Controllers/DashboardController.cs +++ b/Webzine.WebApplication/Areas/Administration/Controllers/DashboardController.cs @@ -5,8 +5,11 @@ using Microsoft.AspNetCore.Mvc; using Webzine.Business.Contracts; using Webzine.Business.Contracts.Dto; +/// +/// Contrôleur pour gérer le tableau de bord de l'administration. +/// [Area("Administration")] -public class DashboardController : Controller // TODO à refaire +public class DashboardController : Controller { private readonly ILogger logger; private readonly IDashboardService dashboardService; diff --git a/Webzine.WebApplication/Areas/Administration/Controllers/StyleController.cs b/Webzine.WebApplication/Areas/Administration/Controllers/StyleController.cs index 2938836..51b9d80 100644 --- a/Webzine.WebApplication/Areas/Administration/Controllers/StyleController.cs +++ b/Webzine.WebApplication/Areas/Administration/Controllers/StyleController.cs @@ -2,9 +2,10 @@ namespace Webzine.WebApplication.Areas.Administration.Controllers; using Microsoft.AspNetCore.Mvc; +using ViewModels.Styles; + using Webzine.Entity; using Webzine.Repository.Contracts; -using Webzine.WebApplication.Areas.Administration.ViewModels.Style; /// /// Controleur pour la gestion des styles dans l'administration du webzine. @@ -77,11 +78,6 @@ public class StyleController : Controller [HttpPost] public IActionResult Create(StyleCreateViewModel model) { - if (!this.ModelState.IsValid) - { - return this.View(model); - } - var style = new Style { Libelle = model.Libelle, @@ -138,7 +134,6 @@ public class StyleController : Controller /// /// L'identifiant du style a editer. /// La vue d'edition ou une redirection vers l'index si le style n'existe pas. - [HttpGet] public IActionResult Edit(int id) { var style = this.styleRepository.Find(id); @@ -165,11 +160,6 @@ public class StyleController : Controller [HttpPost] public IActionResult Edit(StyleEditViewModel model) { - if (!this.ModelState.IsValid) - { - return this.View(model); - } - var style = this.styleRepository.Find(model.IdStyle); if (style == null) { diff --git a/Webzine.WebApplication/Areas/Administration/Controllers/TitreController.cs b/Webzine.WebApplication/Areas/Administration/Controllers/TitreController.cs index c8b0281..a42bdb4 100644 --- a/Webzine.WebApplication/Areas/Administration/Controllers/TitreController.cs +++ b/Webzine.WebApplication/Areas/Administration/Controllers/TitreController.cs @@ -114,13 +114,35 @@ public class TitreController : Controller [HttpPost] public IActionResult Create(TitreAdminDTO model) { - if (this.ModelState.IsValid) + if (!this.ModelState.IsValid) { - this.titreAdminService.CreerTitre(model); - return this.RedirectToAction("Index"); + var form = new AdminTitreForm + { + IdArtiste = model.IdArtiste, + Libelle = model.Libelle, + Album = model.Album, + Chronique = model.Chronique, + DateSortie = model.DateSortie, + Duree = model.Duree, + UrlJaquette = model.UrlJaquette, + UrlEcoute = model.UrlEcoute, + Styles = model.Styles, + Artistes = this.artisteRepository.FindAll().Select(a => new SelectListItem + { + Value = a.IdArtiste.ToString(), + Text = a.Nom, + }).ToList(), + AllStyles = this.styleRepository.FindAll().Select(s => new SelectListItem + { + Value = s.IdStyle.ToString(), + Text = s.Libelle, + }).ToList(), + }; + return this.View(form); } - return this.View(model); + this.titreAdminService.CreerTitre(model); + return this.RedirectToAction("Index"); } /// @@ -171,13 +193,36 @@ public class TitreController : Controller [HttpPost] public IActionResult Edit(TitreAdminDTO model) { - if (this.ModelState.IsValid) + if (!this.ModelState.IsValid) { - this.titreAdminService.ModifierTitre(model); - return this.RedirectToAction("Index"); + var form = new AdminTitreForm + { + Id = model.Id, + IdArtiste = model.IdArtiste, + Libelle = model.Libelle, + Album = model.Album, + Chronique = model.Chronique, + DateSortie = model.DateSortie, + Duree = model.Duree, + UrlJaquette = model.UrlJaquette, + UrlEcoute = model.UrlEcoute, + Styles = model.Styles, + Artistes = this.artisteRepository.FindAll().Select(a => new SelectListItem + { + Value = a.IdArtiste.ToString(), + Text = a.Nom, + }).ToList(), + AllStyles = this.styleRepository.FindAll().Select(s => new SelectListItem + { + Value = s.IdStyle.ToString(), + Text = s.Libelle, + }).ToList(), + }; + return this.View(form); } - return this.View(model); + this.titreAdminService.ModifierTitre(model); + return this.RedirectToAction("Index"); } /// diff --git a/Webzine.WebApplication/Areas/Administration/ViewModels/Artiste/AdminArtisteForm.cs b/Webzine.WebApplication/Areas/Administration/ViewModels/Artiste/AdminArtisteForm.cs index c1700cb..ee14731 100644 --- a/Webzine.WebApplication/Areas/Administration/ViewModels/Artiste/AdminArtisteForm.cs +++ b/Webzine.WebApplication/Areas/Administration/ViewModels/Artiste/AdminArtisteForm.cs @@ -14,11 +14,11 @@ /// /// Définit le nom de l'artiste. /// - public string Nom { get; set; } + public string? Nom { get; set; } /// /// Définit la biographie de l'artiste. /// - public string Biographie { get; set; } + public string? Biographie { get; set; } } } \ No newline at end of file diff --git a/Webzine.WebApplication/Areas/Administration/ViewModels/Artiste/ArtisteCreateViewModel.cs b/Webzine.WebApplication/Areas/Administration/ViewModels/Artiste/ArtisteCreateViewModel.cs index bdb43de..68dedd6 100644 --- a/Webzine.WebApplication/Areas/Administration/ViewModels/Artiste/ArtisteCreateViewModel.cs +++ b/Webzine.WebApplication/Areas/Administration/ViewModels/Artiste/ArtisteCreateViewModel.cs @@ -10,12 +10,15 @@ /// /// Nom de l'artiste. /// - [Required] + [Required(ErrorMessage = "Le nom de l'auteur est obligatoire.")] + [StringLength(50, ErrorMessage = "Le nom ne doit pas dépasser 50 caractères.")] public string Nom { get; set; } /// /// Biographie de l'artiste. - /// + /// * + [Required(ErrorMessage = "La biographie ne peux pas etre vide.")] + public string Biographie { get; set; } } } \ No newline at end of file diff --git a/Webzine.WebApplication/Areas/Administration/ViewModels/Artiste/ArtisteEditViewModel.cs b/Webzine.WebApplication/Areas/Administration/ViewModels/Artiste/ArtisteEditViewModel.cs index bf2d503..7d40252 100644 --- a/Webzine.WebApplication/Areas/Administration/ViewModels/Artiste/ArtisteEditViewModel.cs +++ b/Webzine.WebApplication/Areas/Administration/ViewModels/Artiste/ArtisteEditViewModel.cs @@ -16,12 +16,11 @@ /// /// Nom de l'artiste. /// - [Required] + [Required(ErrorMessage = "Le nom de l'auteur est obligatoire.")] + [StringLength(50, ErrorMessage = "Le nom ne doit pas dépasser 50 caractères.")] + public string Nom { get; set; } - /// - /// Biographie de l'artiste. - /// public string Biographie { get; set; } } } \ No newline at end of file diff --git a/Webzine.WebApplication/Areas/Administration/ViewModels/Styles/StyleCreateViewModel.cs b/Webzine.WebApplication/Areas/Administration/ViewModels/Styles/StyleCreateViewModel.cs index 86abbde..de912e7 100644 --- a/Webzine.WebApplication/Areas/Administration/ViewModels/Styles/StyleCreateViewModel.cs +++ b/Webzine.WebApplication/Areas/Administration/ViewModels/Styles/StyleCreateViewModel.cs @@ -2,7 +2,7 @@ // Copyright (c) Equipe 1 - BOBIN, MASI, NODON, VETU. All rights reserved. // -namespace Webzine.WebApplication.Areas.Administration.ViewModels.Style +namespace Webzine.WebApplication.Areas.Administration.ViewModels.Styles { using System.ComponentModel.DataAnnotations; @@ -14,7 +14,7 @@ namespace Webzine.WebApplication.Areas.Administration.ViewModels.Style /// /// Obtient ou définit le libellé du style. /// - [Required] + [Required(ErrorMessage = "Le libelle du style est obligatoire.")] public string Libelle { get; set; } } } \ No newline at end of file diff --git a/Webzine.WebApplication/Areas/Administration/ViewModels/Styles/StyleDeleteViewModel.cs b/Webzine.WebApplication/Areas/Administration/ViewModels/Styles/StyleDeleteViewModel.cs index fc94e54..daade0d 100644 --- a/Webzine.WebApplication/Areas/Administration/ViewModels/Styles/StyleDeleteViewModel.cs +++ b/Webzine.WebApplication/Areas/Administration/ViewModels/Styles/StyleDeleteViewModel.cs @@ -2,7 +2,7 @@ // Copyright (c) Equipe 1 - BOBIN, MASI, NODON, VETU. All rights reserved. // -namespace Webzine.WebApplication.Areas.Administration.ViewModels.Style +namespace Webzine.WebApplication.Areas.Administration.ViewModels.Styles { /// /// ViewModel pour la suppression d'un style en administration. @@ -17,6 +17,6 @@ namespace Webzine.WebApplication.Areas.Administration.ViewModels.Style /// /// Obtient ou définit le libellé du style. /// - public string Libelle { get; set; } + public string? Libelle { get; set; } } } \ No newline at end of file diff --git a/Webzine.WebApplication/Areas/Administration/ViewModels/Styles/StyleEditViewModel.cs b/Webzine.WebApplication/Areas/Administration/ViewModels/Styles/StyleEditViewModel.cs index 093c130..b959456 100644 --- a/Webzine.WebApplication/Areas/Administration/ViewModels/Styles/StyleEditViewModel.cs +++ b/Webzine.WebApplication/Areas/Administration/ViewModels/Styles/StyleEditViewModel.cs @@ -2,7 +2,7 @@ // Copyright (c) Equipe 1 - BOBIN, MASI, NODON, VETU. All rights reserved. // -namespace Webzine.WebApplication.Areas.Administration.ViewModels.Style +namespace Webzine.WebApplication.Areas.Administration.ViewModels.Styles { using System.ComponentModel.DataAnnotations; @@ -19,7 +19,7 @@ namespace Webzine.WebApplication.Areas.Administration.ViewModels.Style /// /// Obtient ou definit le libelle du style. /// - [Required] + [Required(ErrorMessage = "Le libelle du style est obligatoire.")] public string Libelle { get; set; } } } \ No newline at end of file diff --git a/Webzine.WebApplication/Areas/Administration/ViewModels/Titre/AdminTitreForm.cs b/Webzine.WebApplication/Areas/Administration/ViewModels/Titre/AdminTitreForm.cs index 5305732..22c5fd9 100644 --- a/Webzine.WebApplication/Areas/Administration/ViewModels/Titre/AdminTitreForm.cs +++ b/Webzine.WebApplication/Areas/Administration/ViewModels/Titre/AdminTitreForm.cs @@ -1,5 +1,7 @@ namespace Webzine.WebApplication.Areas.Administration.ViewModels.Titre; +using System.ComponentModel.DataAnnotations; + using Microsoft.AspNetCore.Mvc.Rendering; /// @@ -15,36 +17,47 @@ public class AdminTitreForm /// /// Définit l'identifiant de l'artiste associé au titre. /// + [Required(ErrorMessage = "L'id de l'artiste est obligatoire.")] + public int IdArtiste { get; set; } /// /// Définit le titre du titre. /// + [Required(ErrorMessage = "Le labelle est obligatoire.")] + public string Libelle { get; set; } /// /// Définit le nom de l'album associé au titre. /// + [Required(ErrorMessage = "L'album est obligatoire.")] + public string Album { get; set; } /// /// Définit la chronique du titre, peut-être une critique ou une description du titre. /// + [Required(ErrorMessage = "La chronique est obligatoire.")] public string Chronique { get; set; } /// /// Définit la date de sortie du titre. /// + [Required(ErrorMessage = "La date de est obligatoire.")] + public DateTime DateSortie { get; set; } /// /// Définit la durée du titre en secondes. /// + [Required(ErrorMessage = "La durée est obligatoire.")] public int Duree { get; set; } /// /// Définit l'URL de la jaquette de l'album associé au titre. /// + [Required(ErrorMessage = "L'Url de la jaquette est obligatoire.")] public string UrlJaquette { get; set; } /// diff --git a/Webzine.WebApplication/Areas/Administration/Views/Artiste/Create.cshtml b/Webzine.WebApplication/Areas/Administration/Views/Artiste/Create.cshtml index 38f842b..b9dc4ca 100644 --- a/Webzine.WebApplication/Areas/Administration/Views/Artiste/Create.cshtml +++ b/Webzine.WebApplication/Areas/Administration/Views/Artiste/Create.cshtml @@ -11,6 +11,8 @@
+ +
@@ -19,6 +21,8 @@
+ +
diff --git a/Webzine.WebApplication/Areas/Administration/Views/Artiste/_Form.cshtml b/Webzine.WebApplication/Areas/Administration/Views/Artiste/_Form.cshtml index 960ad3f..c7fbf2e 100644 --- a/Webzine.WebApplication/Areas/Administration/Views/Artiste/_Form.cshtml +++ b/Webzine.WebApplication/Areas/Administration/Views/Artiste/_Form.cshtml @@ -6,6 +6,8 @@
+ +
@@ -14,7 +16,10 @@
+ +
+ diff --git a/Webzine.WebApplication/Areas/Administration/Views/Style/Create.cshtml b/Webzine.WebApplication/Areas/Administration/Views/Style/Create.cshtml index c0cb8f7..ddc0c14 100644 --- a/Webzine.WebApplication/Areas/Administration/Views/Style/Create.cshtml +++ b/Webzine.WebApplication/Areas/Administration/Views/Style/Create.cshtml @@ -1,4 +1,4 @@ -@model Webzine.WebApplication.Areas.Administration.ViewModels.Style.StyleCreateViewModel +@model Webzine.WebApplication.Areas.Administration.ViewModels.Styles.StyleCreateViewModel @{ ViewData["Title"] = "Créer un style"; diff --git a/Webzine.WebApplication/Areas/Administration/Views/Style/Delete.cshtml b/Webzine.WebApplication/Areas/Administration/Views/Style/Delete.cshtml index 47dad12..61dce02 100644 --- a/Webzine.WebApplication/Areas/Administration/Views/Style/Delete.cshtml +++ b/Webzine.WebApplication/Areas/Administration/Views/Style/Delete.cshtml @@ -1,4 +1,4 @@ -@model Webzine.WebApplication.Areas.Administration.ViewModels.Style.StyleDeleteViewModel +@model Webzine.WebApplication.Areas.Administration.ViewModels.Styles.StyleDeleteViewModel @{ ViewData["Title"] = "Supprimer un style"; diff --git a/Webzine.WebApplication/Areas/Administration/Views/Style/Edit.cshtml b/Webzine.WebApplication/Areas/Administration/Views/Style/Edit.cshtml index 446cabe..bf57f66 100644 --- a/Webzine.WebApplication/Areas/Administration/Views/Style/Edit.cshtml +++ b/Webzine.WebApplication/Areas/Administration/Views/Style/Edit.cshtml @@ -1,4 +1,4 @@ -@model Webzine.WebApplication.Areas.Administration.ViewModels.Style.StyleEditViewModel +@model Webzine.WebApplication.Areas.Administration.ViewModels.Styles.StyleEditViewModel @{ ViewData["Title"] = "Editer un style"; diff --git a/Webzine.WebApplication/Areas/Administration/Views/Titre/_Form.cshtml b/Webzine.WebApplication/Areas/Administration/Views/Titre/_Form.cshtml index d1f4f8c..bc44d5a 100644 --- a/Webzine.WebApplication/Areas/Administration/Views/Titre/_Form.cshtml +++ b/Webzine.WebApplication/Areas/Administration/Views/Titre/_Form.cshtml @@ -8,6 +8,8 @@ + + @@ -16,6 +18,7 @@
+
@@ -24,6 +27,7 @@
+
@@ -34,6 +38,8 @@ + + @@ -55,6 +61,8 @@ class="form-control" type="number" min="0" /> + + seconds @@ -66,6 +74,8 @@
+ +
diff --git a/Webzine.WebApplication/Controllers/ApiController.cs b/Webzine.WebApplication/Controllers/ApiController.cs index 0327185..5f045f7 100644 --- a/Webzine.WebApplication/Controllers/ApiController.cs +++ b/Webzine.WebApplication/Controllers/ApiController.cs @@ -2,12 +2,14 @@ namespace Webzine.WebApplication.Controllers; using Microsoft.AspNetCore.Mvc; +/// +/// Controller de version de l'API. +/// public class ApiController : ControllerBase { private readonly ILogger logger; /// - /// Initializes a new instance of the class. /// Initialise une nouvelle instance de la classe . /// /// Service de journalisation injecté pour enregistrer les événements et les erreurs. @@ -21,7 +23,6 @@ public class ApiController : ControllerBase /// Endpoint de test pour vérifier que l'API fonctionne correctement. Retourne un objet JSON contenant le nom et la version de l'application. ///
/// Un objet JSON avec les propriétés "nom" et "version". - [HttpGet] public IActionResult Version() { this.logger.LogInformation("Get Version was called"); diff --git a/Webzine.WebApplication/Controllers/ArtisteController.cs b/Webzine.WebApplication/Controllers/ArtisteController.cs index bc3c40a..9980afa 100644 --- a/Webzine.WebApplication/Controllers/ArtisteController.cs +++ b/Webzine.WebApplication/Controllers/ArtisteController.cs @@ -7,7 +7,6 @@ /// /// Contrôleur pour la gestion des artistes dans l'administration du webzine. Ce contrôleur gère les opérations de création, modification, suppression et affichage des artistes dans l'interface d'administration du webzine. Chaque action du contrôleur prépare un ViewModel spécifique pour la vue correspondante, permettant ainsi une séparation claire entre la logique métier et la présentation des données. - /// /// public class ArtisteController : Controller { diff --git a/Webzine.WebApplication/Controllers/TitreController.cs b/Webzine.WebApplication/Controllers/TitreController.cs index 0b824c0..d5ee70b 100644 --- a/Webzine.WebApplication/Controllers/TitreController.cs +++ b/Webzine.WebApplication/Controllers/TitreController.cs @@ -118,7 +118,7 @@ namespace Webzine.WebApplication.Controllers this.titreRepository.IncrementNbLikes(titre); } - return this.RedirectToAction("Details", new { id = model.IdTitre }); + return this.RedirectToAction("Index", new { id = model.IdTitre }); } /// @@ -129,12 +129,6 @@ namespace Webzine.WebApplication.Controllers [HttpPost] public IActionResult Comment(TitreComment model) { - if (!this.ModelState.IsValid) - { - this.logger.LogWarning("Echec de validation du modele de commentaire pour le titre ID {Id}.", model.IdTitre); - return this.RedirectToAction("Details", new { id = model.IdTitre }); - } - var titre = this.titreRepository.Find(model.IdTitre); if (titre == null) @@ -155,7 +149,7 @@ namespace Webzine.WebApplication.Controllers this.logger.LogInformation("Commentaire ajoute avec succes au titre ID {Id}.", model.IdTitre); - return this.RedirectToAction("Details", new { id = model.IdTitre }); + return this.RedirectToAction("Index", new { id = model.IdTitre }); } private static TitreStyleItem MapTitreItem(Titre titre) diff --git a/Webzine.WebApplication/Filters/GlobalExceptionFilter.cs b/Webzine.WebApplication/Filters/GlobalExceptionFilter.cs new file mode 100644 index 0000000..15f9b73 --- /dev/null +++ b/Webzine.WebApplication/Filters/GlobalExceptionFilter.cs @@ -0,0 +1,42 @@ +namespace Webzine.WebApplication.Filters; + +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; + +/// +/// Filtre d'exception global qui intercepte toute exception non gérée et la journalise automatiquement. +/// +public class GlobalExceptionFilter : IExceptionFilter +{ + private readonly ILogger logger; + + /// + /// Initializes a new instance of the class. + /// + /// Service de journalisation injecté. + public GlobalExceptionFilter(ILogger logger) + { + this.logger = logger; + } + + /// + public void OnException(ExceptionContext context) + { + this.logger.LogError( + context.Exception, + "Erreur non gérée dans {Action} : {Message}", + context.ActionDescriptor.DisplayName, + context.Exception.Message); + + context.Result = new ObjectResult(new + { + erreur = "Une erreur inattendue est survenue.", + detail = context.Exception.Message, + }) + { + StatusCode = StatusCodes.Status500InternalServerError, + }; + + context.ExceptionHandled = true; + } +} \ No newline at end of file diff --git a/Webzine.WebApplication/Filters/ValidationActionFilter.cs b/Webzine.WebApplication/Filters/ValidationActionFilter.cs new file mode 100644 index 0000000..94d0efa --- /dev/null +++ b/Webzine.WebApplication/Filters/ValidationActionFilter.cs @@ -0,0 +1,73 @@ +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) + { + 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)); + + string actionName = context.RouteData.Values["action"]?.ToString() ?? string.Empty; + + // 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) + { + } +} \ No newline at end of file diff --git a/Webzine.WebApplication/Program.cs b/Webzine.WebApplication/Program.cs index be8a92c..4fcbc78 100644 --- a/Webzine.WebApplication/Program.cs +++ b/Webzine.WebApplication/Program.cs @@ -15,6 +15,7 @@ using Webzine.Repository; using Webzine.Repository.Contracts; using Webzine.WebApplication.Configuration; using Webzine.WebApplication.Extensions; +using Webzine.WebApplication.Filters; using Webzine.WebApplication.Interceptors; // Initiation du logger NLog pour la classe courante afin de pouvoir l'utiliser pour logger des messages d'information, d'erreur, etc avant la construction de l'application. @@ -27,7 +28,11 @@ try // Ajoute les services necessaires pour permettre l'utilisation des // controllers avec des vues. - builder.Services.AddControllersWithViews() + builder.Services.AddControllersWithViews(options => + { + // options.Filters.Add(); + options.Filters.Add(); + }) // Ajoute la compilation des vues lors de l'execution de l'application. // Cela nous evite de recompiler l'application a chaque modification de vue. @@ -87,6 +92,9 @@ try builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + // https://learn.microsoft.com/fr-fr/aspnet/core/performance/response-compression?view=aspnetcore-10.0#configuration // Ajoute le service de compression des réponses HTTP pour réduire la taille des données envoyées au client et améliorer les performances de l'application. builder.Services.AddResponseCompression(); diff --git a/Webzine.WebApplication/Views/Titre/Index.cshtml b/Webzine.WebApplication/Views/Titre/Index.cshtml index d668fd9..102c321 100644 --- a/Webzine.WebApplication/Views/Titre/Index.cshtml +++ b/Webzine.WebApplication/Views/Titre/Index.cshtml @@ -60,13 +60,14 @@
- +
- + Editer @@ -88,7 +89,7 @@ class="img-fluid rounded shadow" alt="Jaquette" loading="lazy" - fetchpriority="high" /> + fetchpriority="high"/>
@@ -121,7 +122,7 @@ + required/> @@ -131,10 +132,10 @@
+ rows="3" + class="form-control input-full" + placeholder="Votre commentaire..." + required>
@@ -156,7 +157,7 @@

Commentaires

- @if (Model.Details.Commentaires != null && Model.Details.Commentaires.Any()) + @if (Model.Details.Commentaires.Any()) { foreach (var comment in Model.Details.Commentaires.OrderByDescending(c => c.DateCreation)) { @@ -169,7 +170,7 @@ width="50" height="50" class="rounded-circle me-3 shadow-sm" - alt="avatar" /> + alt="avatar"/>
@comment.Auteur, diff --git a/Webzine.WebApplication/Views/Titre/Style.cshtml b/Webzine.WebApplication/Views/Titre/Style.cshtml index 1c50f0c..6970347 100644 --- a/Webzine.WebApplication/Views/Titre/Style.cshtml +++ b/Webzine.WebApplication/Views/Titre/Style.cshtml @@ -26,7 +26,7 @@
- @titre.Libelle @@ -41,7 +41,7 @@ @titre.ArtisteNom - - @titre.Libelle diff --git a/Webzine.WebApplication/appsettings.json b/Webzine.WebApplication/appsettings.json index 6e9a945..f311284 100644 --- a/Webzine.WebApplication/appsettings.json +++ b/Webzine.WebApplication/appsettings.json @@ -16,6 +16,6 @@ }, "AllowedHosts": "*", "EfPerformance": { - "SeuilMs": 10 + "SeuilMs": 60 } } \ No newline at end of file