Pour réutiliser un script commun, créez une vue partielle contenant le code JavaScript, puis incluez-la dans les pages nécessaires avec la directive suivante :
@Html.Partial("~/Views/Shared/MesScripts.cshtml")
- Valeur par défaut pour DropDownListFor
Lors de l'utilisation de DropDownListFor, le nom de la propriété dans ViewBag ne doit pas correspondre au nom du champ lié au modèle, sinon la sélection par défaut ne s'affichera pas.
@* Vue *@
@Html.DropDownListFor(m => m.MonType, ViewBag.ListeTypes as SelectList, new { @class = "form-control" })
@* Contrôleur *@
string valeurDefaut = "ABC";
string[] typesDisponibles = new string[] { "ABC", "DEF", "GHI" };
List<SelectListItem> elements = new List<SelectListItem>();
foreach (var t in typesDisponibles)
{
if (valeurDefaut == t)
elements.Add(new SelectListItem { Text = t, Value = t, Selected = true });
else
elements.Add(new SelectListItem { Text = t, Value = t });
}
ViewBag.ListeTypes = new SelectList(elements, "Value", "Text");
- Méthodes async sans valeur de retour
Pour une méthode asynchrone qui ne renvoie rien, utilisez Task comme type de retour, et non void.
private async Task InitialiserModele(MonModele modele)
{
// Logique d'initialisation
}
- Intercepter les erreurs Entity Framwork
Pour capturer les détails d'une erreur de validation EF :
try
{
await scope.SaveChangesAsync();
}
catch (System.Data.Entity.Validation.DbEntityValidationException ex)
{
var erreur = ex.EntityValidationErrors.First().ValidationErrors.First();
Console.WriteLine($"{erreur.PropertyName} : {erreur.ErrorMessage}");
}
- Affichage de HTML brut depuis le contrôleur
Utilisez @Html.Raw() pour afficher du contenu HTML sans encodage.
- Mise à jour d'entités avec Entity Framework
Lors d'une mise à jour, évitez d'inclure l'objet à modifier ou d'utiliser le mot-clé virtual sur ses propriétés, car cela peut perturber le suivi des changements.
using (var scope = _dbContextScopeFactory.Create())
{
var db = scope.DbContexts.Get<MonContexte>();
var entite = db.Produits.Find(dto.Id);
dto.EstActif = entite.EstActif;
dto.ProduitId = entite.ProduitId;
dto.Createur = entite.Createur;
_mapper.Map(dto, entite);
entite.MarquerModifie();
entite.Categorie = await db.Categories.FirstOrDefaultAsync(c => c.Id == dto.CategorieId);
await scope.SaveChangesAsync();
return true;
}
Remarque sur Find : Find vérifie d'abord si l'entité est dans le cache du contexte avant d'interroger la base de données, contrairement à FirstOrDefault ou Where.
- Propriétés virtuelles et chargement automatique
Une propriété de navigation marquée virtual est chargée automatiquement (lazy loading) sans nécessiter Include.
- Inclusion implicite via la sélection
Si une requête projette directement des champs d'une entité liée, l'Include explicite n'est pas nécessaire.
var resultats = db.Commandes
.Where(c => !c.EstSupprime)
.Select(c => new HistoriqueCommandeDto
{
Id = c.Id,
Utilisateur = new UtilisateurDto { /* Champs */ }
});
- Définir un délai d'exécution pour une commande EF
var db = scope.DbContexts.Get<MonContexte>();
db.Database.CommandTimeout = 120; // 2 minutes
- Protection CSRF dans MVC
Ajoutez @Html.AntiForgeryToken() dans le formulaire HTML et décorez l'action du contrôleur avec [ValidateAntiForgeryToken] pour les requêtes POST.
- Fonctions de traduction SQL
Utilisez les méthodes de System.Data.Objects.SqlClient.SqlFunctions ou System.Data.Objects.EntityFunctions pour comparer des dates.
// avec SqlFunctions
.Where(u => SqlFunctions.DateDiff("s", DateTime.Now, u.DateHeure) > 0)
// avec EntityFunctions
.Where(u => EntityFunctions.DiffSeconds(DateTime.Now, u.DateHeure) > 0)
- Appel synchrone d'une méthode async
var service = DependencyResolver.Current.GetService<IMonService>();
var donnees = Task.Run(async () => await service.ObtenirDonneesAsync("cle"))
.ConfigureAwait(false).GetAwaiter().GetResult();
- Utilitaires JavaScript pour JSON
JSON.parse(chaineJson); // Convertit une chaîne en objet JSON
JSON.stringify(objetJson); // Convertit un objet en chaîne JSON
- Optimisation de la pagination EF
a) Évitez les jointures multiples : récupérez les données principales, puis complétez les objets liés après la pagination.
var resultats = await requete
.OrderByDescending(r => r.DateCreation)
.Select(r => new MonDto { Id = r.Id, /* champs essentiels */ })
.PagingAsync(page, taille);
foreach (var item in resultats.Items)
{
item.Utilisateur = db.Utilisateurs
.Where(u => u.Id == item.UtilisateurId)
.Select(u => new UtilisateurDto { /* champs */ })
.FirstOrDefault();
}
b) Index composé : incluez la clé primaire avant le champ de tri pour améliorer les performances.
- Erreur de compilation "accès refusé" à bin\roslyn
Mettez à jour le package NuGet Microsoft.CodeDom.Providers.DotNetCompilerPlatform vers la version 1.0.7 ou supérieure.
- Réinitialisation des répertoires virtuels dans VS
Ouvrez le fichier .vs/config/applicationhost.config, localisez la section <sites> et supprimez les répertoires virtuels superflus.
- Validation distante avec plusieurs champs
[Remote("EstExistant", "Utilisateur", AdditionalFields = "Identifiant", ErrorMessage = "L'élément existe déjà.")]
[Remote("EstExistant", "Zone", AdditionalFields = "Identifiant,ParentIdentifiant", ErrorMessage = "La zone existe déjà.")]
- Ordre d'exécution des filtres
OnAuthorization (dans AuthorizeAttribute) s'exécute avant OnActionExecuting (dans ActionFilterAttribute).
- Support GET/POST pour les WebAPI
Si une méthode commence par Get, elle n'accepte que les requêtes GET. Pour accepter POST, ajoutez les attributs [HttpPost] et [HttpGet].
- Désactiver l'auto-incrémentation d'une clé primaire
this.Property(p => p.CodeRegion)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
- Désactiver la suppression en cascade
this.HasRequired(s => s.Zone)
.WithMany()
.HasForeignKey(s => s.ZoneAssociee)
.WillCascadeOnDelete(false);
- Contrôle du type de jointure (INNER ou LEFT)
// Génère une jointure INNER
HasRequired(s => s.SalleDeClasse)
// Génère une jointure LEFT
HasOptional(s => s.SalleDeClasse)
- Configuration du contexte EF
context.Configuration.LazyLoadingEnabled = false;
context.Configuration.ProxyCreationEnabled = false;
context.Configuration.AutoDetectChangesEnabled = false;
- Validation des champs cachés
Ajoutez ce script pour forcer la validation des éléments input[type="hidden"] :
$.validator.setDefaults({ ignore: [] });
- Attributs HTML personnalisés avec tirets
Remplacez le tiret par un underscore :
@Html.DropDownList("maListe", ... , new { @class = "form-control", @data_recherche_en_direct = "true" })
- Résolution de dépendances Autofac en contexte asynchrone
var resolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
// Récupération
var service = GlobalConfiguration.Configuration
.DependencyResolver
.GetService(typeof(MonService)) as MonService;
- Appel synchrone d'une méthode async dans ASP.NET Core
AsyncHelper.RunSync(() => monService.AbonnerAsync(param1, param2, param3));
- Exécution parallèle avec WhenAll
using (var db = new MonContexte())
{
var clients = db.Clients.ToListAsync();
var serveurs = db.Serveurs.ToListAsync();
await Task.WhenAll(clients, serveurs);
}
- Supppression des conditions NULL superflues dans le SQL généré
this.Configuration.UseDatabaseNullSemantics = true;
// Pour gérer les nulls explicitement :
query = valeur == null
? query.Where(e => e.Champ == null)
: query.Where(e => e.Champ == valeur);
- Sommes multi-champs avec EF
// Avec regroupement
query.GroupBy(q => new { q.Annee, q.Mois })
.Select(g => new {
Annee = g.Key.Annee,
Mois = g.Key.Mois,
TotalMontant = g.Sum(i => i.Montant),
TotalRecu = g.Sum(i => i.Recu)
});
// Sans regroupement (total général)
query.GroupBy(x => new { })
.Select(g => new {
PoidsTotal = g.Sum(x => x.Poids),
QuantiteTotale = g.Sum(x => x.Quantite)
}).FirstOrDefault();
- Configuration d'une relation un-à-plusieurs avec Code First
Table principale :
public class Contrat : EntiteBase
{
public string NomContrat { get; set; }
public List<ModeleContrat> Modeles { get; set; }
public Statut Etat { get; set; }
}
public class ContratMap : EntityTypeConfiguration<Contrat>
{
public ContratMap()
{
ToTable("Contrat");
HasKey(c => c.Id);
Property(c => c.NomContrat).IsRequired().HasMaxLength(100);
HasMany(c => c.Modeles).WithOptional().HasForeignKey(m => m.ContratId);
}
}
Table enfant :
public class ModeleContrat : EntiteBase
{
public int ContratId { get; set; }
public string Version { get; set; }
public string CheminFichier { get; set; }
}
- Validation personnalisée
Créez une classe qui hérite de Attribute et implémente IModelValidator.
- Validation distante avec nameof
[Remote(nameof(RoleController.VerifierExistenceRole), "Role", ErrorMessage = "Ce rôle existe déjà.")]