(Rebase) Resolution de merge conflit entre dev et j3/feat/pagination
This commit is contained in:
@@ -26,12 +26,7 @@
|
|||||||
<ProjectReference Include="..\Webzine.Business.Contracts\Webzine.Business.Contracts.csproj" />
|
<ProjectReference Include="..\Webzine.Business.Contracts\Webzine.Business.Contracts.csproj" />
|
||||||
<ProjectReference Include="..\Webzine.Entity\Webzine.Entity.csproj" />
|
<ProjectReference Include="..\Webzine.Entity\Webzine.Entity.csproj" />
|
||||||
<ProjectReference Include="..\Webzine.Repository.Contracts\Webzine.Repository.Contracts.csproj" />
|
<ProjectReference Include="..\Webzine.Repository.Contracts\Webzine.Repository.Contracts.csproj" />
|
||||||
</ItemGroup>
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0-preview.1.25080.5" />
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions">
|
|
||||||
<HintPath>..\..\..\..\..\..\..\.nuget\packages\microsoft.extensions.logging.abstractions\10.0.5\lib\net10.0\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ public class DbStyleRepository : IStyleRepository
|
|||||||
this.logger.LogDebug("Recherche du style avec l'ID: {Id}", id);
|
this.logger.LogDebug("Recherche du style avec l'ID: {Id}", id);
|
||||||
|
|
||||||
var style = this.context.Styles
|
var style = this.context.Styles
|
||||||
.AsNoTracking()
|
|
||||||
.Include(s => s.Titres)
|
.Include(s => s.Titres)
|
||||||
.SingleOrDefault(s => s.IdStyle == id);
|
.SingleOrDefault(s => s.IdStyle == id);
|
||||||
|
|
||||||
@@ -123,7 +122,6 @@ public class DbStyleRepository : IStyleRepository
|
|||||||
this.logger.LogDebug("Tri des styles par libellé");
|
this.logger.LogDebug("Tri des styles par libellé");
|
||||||
|
|
||||||
var styles = this.context.Styles
|
var styles = this.context.Styles
|
||||||
.AsNoTracking()
|
|
||||||
.OrderBy(s => s.Libelle);
|
.OrderBy(s => s.Libelle);
|
||||||
|
|
||||||
this.logger.LogDebug("La liste de styles a été récupérée.");
|
this.logger.LogDebug("La liste de styles a été récupérée.");
|
||||||
|
|||||||
@@ -74,14 +74,6 @@ public class ArtisteController : Controller
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult Create(ArtisteCreateViewModel model)
|
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.
|
// Créer un objet Artiste avecc les paramètres.
|
||||||
var artiste = new Artiste
|
var artiste = new Artiste
|
||||||
{
|
{
|
||||||
@@ -121,18 +113,16 @@ public class ArtisteController : Controller
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult Edit(ArtisteEditViewModel model)
|
public IActionResult Edit(ArtisteEditViewModel model)
|
||||||
{
|
{
|
||||||
var artiste = new Artiste
|
var artiste = this.artisteRepository.Find(model.Id);
|
||||||
{
|
|
||||||
IdArtiste = model.Id,
|
|
||||||
Nom = model.Nom,
|
|
||||||
Biographie = model.Biographie,
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
this.artisteRepository.Update(artiste);
|
||||||
|
|
||||||
return this.RedirectToAction("Index");
|
return this.RedirectToAction("Index");
|
||||||
|
|||||||
@@ -96,11 +96,6 @@ namespace Webzine.WebApplication.Areas.Administration.Controllers
|
|||||||
{
|
{
|
||||||
var commentaire = this.commentaireRepository.Find(model.IdCommentaire);
|
var commentaire = this.commentaireRepository.Find(model.IdCommentaire);
|
||||||
|
|
||||||
if (!this.ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return this.View(commentaire);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commentaire != null)
|
if (commentaire != null)
|
||||||
{
|
{
|
||||||
this.commentaireRepository.Delete(commentaire);
|
this.commentaireRepository.Delete(commentaire);
|
||||||
|
|||||||
@@ -5,8 +5,11 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Webzine.Business.Contracts;
|
using Webzine.Business.Contracts;
|
||||||
using Webzine.Business.Contracts.Dto;
|
using Webzine.Business.Contracts.Dto;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contrôleur pour gérer le tableau de bord de l'administration.
|
||||||
|
/// </summary>
|
||||||
[Area("Administration")]
|
[Area("Administration")]
|
||||||
public class DashboardController : Controller // TODO à refaire
|
public class DashboardController : Controller
|
||||||
{
|
{
|
||||||
private readonly ILogger<DashboardController> logger;
|
private readonly ILogger<DashboardController> logger;
|
||||||
private readonly IDashboardService dashboardService;
|
private readonly IDashboardService dashboardService;
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ namespace Webzine.WebApplication.Areas.Administration.Controllers;
|
|||||||
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
using ViewModels.Styles;
|
||||||
|
|
||||||
using Webzine.Entity;
|
using Webzine.Entity;
|
||||||
using Webzine.Repository.Contracts;
|
using Webzine.Repository.Contracts;
|
||||||
using Webzine.WebApplication.Areas.Administration.ViewModels.Style;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Controleur pour la gestion des styles dans l'administration du webzine.
|
/// Controleur pour la gestion des styles dans l'administration du webzine.
|
||||||
@@ -77,11 +78,6 @@ public class StyleController : Controller
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult Create(StyleCreateViewModel model)
|
public IActionResult Create(StyleCreateViewModel model)
|
||||||
{
|
{
|
||||||
if (!this.ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return this.View(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
var style = new Style
|
var style = new Style
|
||||||
{
|
{
|
||||||
Libelle = model.Libelle,
|
Libelle = model.Libelle,
|
||||||
@@ -138,7 +134,6 @@ public class StyleController : Controller
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">L'identifiant du style a editer.</param>
|
/// <param name="id">L'identifiant du style a editer.</param>
|
||||||
/// <returns>La vue d'edition ou une redirection vers l'index si le style n'existe pas.</returns>
|
/// <returns>La vue d'edition ou une redirection vers l'index si le style n'existe pas.</returns>
|
||||||
[HttpGet]
|
|
||||||
public IActionResult Edit(int id)
|
public IActionResult Edit(int id)
|
||||||
{
|
{
|
||||||
var style = this.styleRepository.Find(id);
|
var style = this.styleRepository.Find(id);
|
||||||
@@ -165,11 +160,6 @@ public class StyleController : Controller
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult Edit(StyleEditViewModel model)
|
public IActionResult Edit(StyleEditViewModel model)
|
||||||
{
|
{
|
||||||
if (!this.ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return this.View(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
var style = this.styleRepository.Find(model.IdStyle);
|
var style = this.styleRepository.Find(model.IdStyle);
|
||||||
if (style == null)
|
if (style == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -114,13 +114,35 @@ public class TitreController : Controller
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult Create(TitreAdminDTO model)
|
public IActionResult Create(TitreAdminDTO model)
|
||||||
{
|
{
|
||||||
if (this.ModelState.IsValid)
|
if (!this.ModelState.IsValid)
|
||||||
{
|
{
|
||||||
this.titreAdminService.CreerTitre(model);
|
var form = new AdminTitreForm
|
||||||
return this.RedirectToAction("Index");
|
{
|
||||||
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -171,13 +193,36 @@ public class TitreController : Controller
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult Edit(TitreAdminDTO model)
|
public IActionResult Edit(TitreAdminDTO model)
|
||||||
{
|
{
|
||||||
if (this.ModelState.IsValid)
|
if (!this.ModelState.IsValid)
|
||||||
{
|
{
|
||||||
this.titreAdminService.ModifierTitre(model);
|
var form = new AdminTitreForm
|
||||||
return this.RedirectToAction("Index");
|
{
|
||||||
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -14,11 +14,11 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Définit le nom de l'artiste.
|
/// Définit le nom de l'artiste.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Nom { get; set; }
|
public string? Nom { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Définit la biographie de l'artiste.
|
/// Définit la biographie de l'artiste.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Biographie { get; set; }
|
public string? Biographie { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,12 +10,15 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Nom de l'artiste.
|
/// Nom de l'artiste.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[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; }
|
public string Nom { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Biographie de l'artiste.
|
/// Biographie de l'artiste.
|
||||||
/// </summary>
|
/// </summary>*
|
||||||
|
[Required(ErrorMessage = "La biographie ne peux pas etre vide.")]
|
||||||
|
|
||||||
public string Biographie { get; set; }
|
public string Biographie { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,12 +16,11 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Nom de l'artiste.
|
/// Nom de l'artiste.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[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; }
|
public string Nom { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Biographie de l'artiste.
|
|
||||||
/// </summary>
|
|
||||||
public string Biographie { get; set; }
|
public string Biographie { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Copyright (c) Equipe 1 - BOBIN, MASI, NODON, VETU. All rights reserved.
|
// Copyright (c) Equipe 1 - BOBIN, MASI, NODON, VETU. All rights reserved.
|
||||||
// </copyright>
|
// </copyright>
|
||||||
|
|
||||||
namespace Webzine.WebApplication.Areas.Administration.ViewModels.Style
|
namespace Webzine.WebApplication.Areas.Administration.ViewModels.Styles
|
||||||
{
|
{
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ namespace Webzine.WebApplication.Areas.Administration.ViewModels.Style
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Obtient ou définit le libellé du style.
|
/// Obtient ou définit le libellé du style.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Required]
|
[Required(ErrorMessage = "Le libelle du style est obligatoire.")]
|
||||||
public string Libelle { get; set; }
|
public string Libelle { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Copyright (c) Equipe 1 - BOBIN, MASI, NODON, VETU. All rights reserved.
|
// Copyright (c) Equipe 1 - BOBIN, MASI, NODON, VETU. All rights reserved.
|
||||||
// </copyright>
|
// </copyright>
|
||||||
|
|
||||||
namespace Webzine.WebApplication.Areas.Administration.ViewModels.Style
|
namespace Webzine.WebApplication.Areas.Administration.ViewModels.Styles
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ViewModel pour la suppression d'un style en administration.
|
/// ViewModel pour la suppression d'un style en administration.
|
||||||
@@ -17,6 +17,6 @@ namespace Webzine.WebApplication.Areas.Administration.ViewModels.Style
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Obtient ou définit le libellé du style.
|
/// Obtient ou définit le libellé du style.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Libelle { get; set; }
|
public string? Libelle { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Copyright (c) Equipe 1 - BOBIN, MASI, NODON, VETU. All rights reserved.
|
// Copyright (c) Equipe 1 - BOBIN, MASI, NODON, VETU. All rights reserved.
|
||||||
// </copyright>
|
// </copyright>
|
||||||
|
|
||||||
namespace Webzine.WebApplication.Areas.Administration.ViewModels.Style
|
namespace Webzine.WebApplication.Areas.Administration.ViewModels.Styles
|
||||||
{
|
{
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ namespace Webzine.WebApplication.Areas.Administration.ViewModels.Style
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Obtient ou definit le libelle du style.
|
/// Obtient ou definit le libelle du style.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Required]
|
[Required(ErrorMessage = "Le libelle du style est obligatoire.")]
|
||||||
public string Libelle { get; set; }
|
public string Libelle { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
namespace Webzine.WebApplication.Areas.Administration.ViewModels.Titre;
|
namespace Webzine.WebApplication.Areas.Administration.ViewModels.Titre;
|
||||||
|
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -15,36 +17,47 @@ public class AdminTitreForm
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Définit l'identifiant de l'artiste associé au titre.
|
/// Définit l'identifiant de l'artiste associé au titre.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "L'id de l'artiste est obligatoire.")]
|
||||||
|
|
||||||
public int IdArtiste { get; set; }
|
public int IdArtiste { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Définit le titre du titre.
|
/// Définit le titre du titre.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "Le labelle est obligatoire.")]
|
||||||
|
|
||||||
public string Libelle { get; set; }
|
public string Libelle { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Définit le nom de l'album associé au titre.
|
/// Définit le nom de l'album associé au titre.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "L'album est obligatoire.")]
|
||||||
|
|
||||||
public string Album { get; set; }
|
public string Album { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Définit la chronique du titre, peut-être une critique ou une description du titre.
|
/// Définit la chronique du titre, peut-être une critique ou une description du titre.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "La chronique est obligatoire.")]
|
||||||
public string Chronique { get; set; }
|
public string Chronique { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Définit la date de sortie du titre.
|
/// Définit la date de sortie du titre.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "La date de est obligatoire.")]
|
||||||
|
|
||||||
public DateTime DateSortie { get; set; }
|
public DateTime DateSortie { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Définit la durée du titre en secondes.
|
/// Définit la durée du titre en secondes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "La durée est obligatoire.")]
|
||||||
public int Duree { get; set; }
|
public int Duree { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Définit l'URL de la jaquette de l'album associé au titre.
|
/// Définit l'URL de la jaquette de l'album associé au titre.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "L'Url de la jaquette est obligatoire.")]
|
||||||
public string UrlJaquette { get; set; }
|
public string UrlJaquette { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
<label class="col-md-3 col-form-label">Nom de l'artiste<span class="text-danger">*</span></label>
|
<label class="col-md-3 col-form-label">Nom de l'artiste<span class="text-danger">*</span></label>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<input asp-for="Nom" class="form-control" />
|
<input asp-for="Nom" class="form-control" />
|
||||||
|
<span asp-validation-for="Nom" class="text-danger"></span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -19,6 +21,8 @@
|
|||||||
<label class="col-md-3 col-form-label">Biographie</label>
|
<label class="col-md-3 col-form-label">Biographie</label>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<textarea asp-for="Biographie" class="form-control" rows="5"></textarea>
|
<textarea asp-for="Biographie" class="form-control" rows="5"></textarea>
|
||||||
|
<span asp-validation-for="Biographie" class="text-danger"></span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
<label class="col-md-3 col-form-label">Nom de l'artiste<span class="text-danger">*</span></label>
|
<label class="col-md-3 col-form-label">Nom de l'artiste<span class="text-danger">*</span></label>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<input asp-for="Nom" class="form-control" />
|
<input asp-for="Nom" class="form-control" />
|
||||||
|
<span asp-validation-for="Nom" class="text-danger"></span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -14,7 +16,10 @@
|
|||||||
<label class="col-md-3 col-form-label">Biographie</label>
|
<label class="col-md-3 col-form-label">Biographie</label>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<textarea asp-for="Biographie" class="form-control" rows="5"></textarea>
|
<textarea asp-for="Biographie" class="form-control" rows="5"></textarea>
|
||||||
|
<span asp-validation-for="Biographie" class="text-danger"></span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- BOUTONS -->
|
<!-- BOUTONS -->
|
||||||
|
|||||||
@@ -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";
|
ViewData["Title"] = "Créer un style";
|
||||||
|
|||||||
@@ -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";
|
ViewData["Title"] = "Supprimer un style";
|
||||||
|
|||||||
@@ -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";
|
ViewData["Title"] = "Editer un style";
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
<select asp-for="IdArtiste"
|
<select asp-for="IdArtiste"
|
||||||
asp-items="Model.Artistes"
|
asp-items="Model.Artistes"
|
||||||
class="form-select"></select>
|
class="form-select"></select>
|
||||||
|
<span asp-validation-for="IdArtiste" class="text-danger"></span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -16,6 +18,7 @@
|
|||||||
<label class="col-md-3 col-form-label">Titre<span class="text-danger">*</span></label>
|
<label class="col-md-3 col-form-label">Titre<span class="text-danger">*</span></label>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<input asp-for="Libelle" class="form-control"/>
|
<input asp-for="Libelle" class="form-control"/>
|
||||||
|
<span asp-validation-for="Libelle" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -24,6 +27,7 @@
|
|||||||
<label class="col-md-3 col-form-label">Album<span class="text-danger">*</span></label>
|
<label class="col-md-3 col-form-label">Album<span class="text-danger">*</span></label>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<input asp-for="Album" class="form-control"/>
|
<input asp-for="Album" class="form-control"/>
|
||||||
|
<span asp-validation-for="Album" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -34,6 +38,8 @@
|
|||||||
<textarea asp-for="Chronique"
|
<textarea asp-for="Chronique"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
rows="5"></textarea>
|
rows="5"></textarea>
|
||||||
|
<span asp-validation-for="Chronique" class="text-danger"></span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -55,6 +61,8 @@
|
|||||||
class="form-control"
|
class="form-control"
|
||||||
type="number"
|
type="number"
|
||||||
min="0" />
|
min="0" />
|
||||||
|
<span asp-validation-for="Duree" class="text-danger"></span>
|
||||||
|
|
||||||
<span class="input-group-text text-muted">seconds</span>
|
<span class="input-group-text text-muted">seconds</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -66,6 +74,8 @@
|
|||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<input asp-for="UrlJaquette"
|
<input asp-for="UrlJaquette"
|
||||||
class="form-control"/>
|
class="form-control"/>
|
||||||
|
<span asp-validation-for="UrlJaquette" class="text-danger"></span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ namespace Webzine.WebApplication.Controllers;
|
|||||||
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controller de version de l'API.
|
||||||
|
/// </summary>
|
||||||
public class ApiController : ControllerBase
|
public class ApiController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ILogger<ApiController> logger;
|
private readonly ILogger<ApiController> logger;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ApiController"/> class.
|
|
||||||
/// Initialise une nouvelle instance de la classe <see cref="ApiController"/>.
|
/// Initialise une nouvelle instance de la classe <see cref="ApiController"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="logger">Service de journalisation injecté pour enregistrer les événements et les erreurs.</param>
|
/// <param name="logger">Service de journalisation injecté pour enregistrer les événements et les erreurs.</param>
|
||||||
@@ -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.
|
/// Endpoint de test pour vérifier que l'API fonctionne correctement. Retourne un objet JSON contenant le nom et la version de l'application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Un objet JSON avec les propriétés "nom" et "version".</returns>
|
/// <returns>Un objet JSON avec les propriétés "nom" et "version".</returns>
|
||||||
[HttpGet]
|
|
||||||
public IActionResult Version()
|
public IActionResult Version()
|
||||||
{
|
{
|
||||||
this.logger.LogInformation("Get Version was called");
|
this.logger.LogInformation("Get Version was called");
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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.
|
/// 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.
|
||||||
///
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ArtisteController : Controller
|
public class ArtisteController : Controller
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ namespace Webzine.WebApplication.Controllers
|
|||||||
this.titreRepository.IncrementNbLikes(titre);
|
this.titreRepository.IncrementNbLikes(titre);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.RedirectToAction("Details", new { id = model.IdTitre });
|
return this.RedirectToAction("Index", new { id = model.IdTitre });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -129,12 +129,6 @@ namespace Webzine.WebApplication.Controllers
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult Comment(TitreComment model)
|
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);
|
var titre = this.titreRepository.Find(model.IdTitre);
|
||||||
|
|
||||||
if (titre == null)
|
if (titre == null)
|
||||||
@@ -155,7 +149,7 @@ namespace Webzine.WebApplication.Controllers
|
|||||||
|
|
||||||
this.logger.LogInformation("Commentaire ajoute avec succes au titre ID {Id}.", model.IdTitre);
|
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)
|
private static TitreStyleItem MapTitreItem(Titre titre)
|
||||||
|
|||||||
42
Webzine.WebApplication/Filters/GlobalExceptionFilter.cs
Normal file
42
Webzine.WebApplication/Filters/GlobalExceptionFilter.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
namespace Webzine.WebApplication.Filters;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Filtre d'exception global qui intercepte toute exception non gérée et la journalise automatiquement.
|
||||||
|
/// </summary>
|
||||||
|
public class GlobalExceptionFilter : IExceptionFilter
|
||||||
|
{
|
||||||
|
private readonly ILogger<GlobalExceptionFilter> logger;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="GlobalExceptionFilter"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">Service de journalisation injecté.</param>
|
||||||
|
public GlobalExceptionFilter(ILogger<GlobalExceptionFilter> logger)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
73
Webzine.WebApplication/Filters/ValidationActionFilter.cs
Normal file
73
Webzine.WebApplication/Filters/ValidationActionFilter.cs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
namespace Webzine.WebApplication.Filters;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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).
|
||||||
|
/// </summary>
|
||||||
|
public class ValidationActionFilter : IActionFilter
|
||||||
|
{
|
||||||
|
private readonly ILogger<ValidationActionFilter> logger;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ValidationActionFilter"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">Service de journalisation injecté.</param>
|
||||||
|
public ValidationActionFilter(ILogger<ValidationActionFilter> logger)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void OnActionExecuted(ActionExecutedContext context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ using Webzine.Repository;
|
|||||||
using Webzine.Repository.Contracts;
|
using Webzine.Repository.Contracts;
|
||||||
using Webzine.WebApplication.Configuration;
|
using Webzine.WebApplication.Configuration;
|
||||||
using Webzine.WebApplication.Extensions;
|
using Webzine.WebApplication.Extensions;
|
||||||
|
using Webzine.WebApplication.Filters;
|
||||||
using Webzine.WebApplication.Interceptors;
|
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.
|
// 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
|
// Ajoute les services necessaires pour permettre l'utilisation des
|
||||||
// controllers avec des vues.
|
// controllers avec des vues.
|
||||||
builder.Services.AddControllersWithViews()
|
builder.Services.AddControllersWithViews(options =>
|
||||||
|
{
|
||||||
|
// options.Filters.Add<GlobalExceptionFilter>();
|
||||||
|
options.Filters.Add<ValidationActionFilter>();
|
||||||
|
})
|
||||||
|
|
||||||
// Ajoute la compilation des vues lors de l'execution de l'application.
|
// Ajoute la compilation des vues lors de l'execution de l'application.
|
||||||
// Cela nous evite de recompiler l'application a chaque modification de vue.
|
// Cela nous evite de recompiler l'application a chaque modification de vue.
|
||||||
@@ -87,6 +92,9 @@ try
|
|||||||
builder.Services.AddScoped<IDashboardService, DashboardService>();
|
builder.Services.AddScoped<IDashboardService, DashboardService>();
|
||||||
builder.Services.AddScoped<ITitreAdminService, TitreAdminService>();
|
builder.Services.AddScoped<ITitreAdminService, TitreAdminService>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<ValidationActionFilter>();
|
||||||
|
builder.Services.AddScoped<GlobalExceptionFilter>();
|
||||||
|
|
||||||
// https://learn.microsoft.com/fr-fr/aspnet/core/performance/response-compression?view=aspnetcore-10.0#configuration
|
// 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.
|
// 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();
|
builder.Services.AddResponseCompression();
|
||||||
|
|||||||
@@ -60,13 +60,14 @@
|
|||||||
<div class="d-flex gap-2">
|
<div class="d-flex gap-2">
|
||||||
|
|
||||||
<form asp-action="Like" method="post">
|
<form asp-action="Like" method="post">
|
||||||
<input type="hidden" name="IdTitre" value="@Model.Details.IdTitre" />
|
<input type="hidden" name="IdTitre" value="@Model.Details.IdTitre"/>
|
||||||
<button type="submit" class="btn btn-outline-primary btn-sm">
|
<button type="submit" class="btn btn-outline-primary btn-sm">
|
||||||
<i class="fa fa-thumbs-up me-1"></i> Like
|
<i class="fa fa-thumbs-up me-1"></i> Like
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<a asp-area="Administration" asp-controller="Titre" asp-action="Edit" asp-route-id="@Model.Details.IdTitre" class="btn text-primary btn-sm">
|
<a asp-area="Administration" asp-controller="Titre" asp-action="Edit"
|
||||||
|
asp-route-id="@Model.Details.IdTitre" class="btn text-primary btn-sm">
|
||||||
<i class="fa fa-pen-to-square me-1"></i> Editer
|
<i class="fa fa-pen-to-square me-1"></i> Editer
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -88,7 +89,7 @@
|
|||||||
class="img-fluid rounded shadow"
|
class="img-fluid rounded shadow"
|
||||||
alt="Jaquette"
|
alt="Jaquette"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
fetchpriority="high" />
|
fetchpriority="high"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -121,7 +122,7 @@
|
|||||||
<input name="Auteur"
|
<input name="Auteur"
|
||||||
class="form-control input-full"
|
class="form-control input-full"
|
||||||
placeholder="Votre nom"
|
placeholder="Votre nom"
|
||||||
required />
|
required/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -131,10 +132,10 @@
|
|||||||
</label>
|
</label>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<textarea name="Contenu"
|
<textarea name="Contenu"
|
||||||
rows="3"
|
rows="3"
|
||||||
class="form-control input-full"
|
class="form-control input-full"
|
||||||
placeholder="Votre commentaire..."
|
placeholder="Votre commentaire..."
|
||||||
required></textarea>
|
required></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -156,7 +157,7 @@
|
|||||||
|
|
||||||
<h4 class="mb-4">Commentaires</h4>
|
<h4 class="mb-4">Commentaires</h4>
|
||||||
|
|
||||||
@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))
|
foreach (var comment in Model.Details.Commentaires.OrderByDescending(c => c.DateCreation))
|
||||||
{
|
{
|
||||||
@@ -169,7 +170,7 @@
|
|||||||
width="50"
|
width="50"
|
||||||
height="50"
|
height="50"
|
||||||
class="rounded-circle me-3 shadow-sm"
|
class="rounded-circle me-3 shadow-sm"
|
||||||
alt="avatar" />
|
alt="avatar"/>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<strong>@comment.Auteur</strong>,
|
<strong>@comment.Auteur</strong>,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
<div class="d-flex align-items-start my-3">
|
<div class="d-flex align-items-start my-3">
|
||||||
|
|
||||||
<!-- Image -->
|
<!-- Image -->
|
||||||
<a asp-action="Details"
|
<a asp-action="Index"
|
||||||
asp-route-id="@titre.IdTitre"
|
asp-route-id="@titre.IdTitre"
|
||||||
class="me-3 text-black">
|
class="me-3 text-black">
|
||||||
<img src="@titre.UrlJaquette" alt="@titre.Libelle" width="70px" height="70px" class="object-fit-cover" loading="lazy"/>
|
<img src="@titre.UrlJaquette" alt="@titre.Libelle" width="70px" height="70px" class="object-fit-cover" loading="lazy"/>
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
@titre.ArtisteNom
|
@titre.ArtisteNom
|
||||||
</a>
|
</a>
|
||||||
-
|
-
|
||||||
<a asp-action="Details"
|
<a asp-action="Index"
|
||||||
asp-route-id="@titre.IdTitre">
|
asp-route-id="@titre.IdTitre">
|
||||||
@titre.Libelle
|
@titre.Libelle
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -16,6 +16,6 @@
|
|||||||
},
|
},
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"EfPerformance": {
|
"EfPerformance": {
|
||||||
"SeuilMs": 10
|
"SeuilMs": 60
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user