________ _ _
| | _| |_| |_
| _____| |_ _ _|
| | _| |_| |_
| |_____ |_ _ _|
| | |_| |_|
|________|
Cours sur le c#
csharp.md 25/08/2023
ultimecool.com
CHAPITRE 1 - C# Généralités 1.1. Visual Studio et Premier programme en C# 1.2. Introduction au language objet: 1.3. Première classe en C# 1.4. Injection de dépendances 1.5. Attributs statiques 1.6. Assemblées (Assemblies) 1.7. Tests unitaires 1.8. Syntaxe structures et tableaux 1.9. Passage de paramètres par référence 1.10. Surdefinition des fonctions: 1.11. Gestion des Evenements 1.12. Gestion des exceptions 1.13. Poo Inheritance 1.14. Classes abstraite 1.15. Interfaces 1.16. Différences entre Classe abstraite et Interface 1.17. Sur definition d'operateurs: 1.18. Classes scéllés 1.19. Les collections 1.20. Documentation du code 1.21. Trace et débug CHAPITRE 2 - Interfaces notions avancées. 2.1. Extensibilité avec les interfaces 2.2. Implementation d'interface explicite 2.3. RepositoryFactory 2.4. La Couche View Model MVVM 2.5. Chargement dynamique 2.6. Dependency Injection 2.7. Mocking 2.8. Méthodes d'extension 2.9. Signal-R CHAPITRE 3 - LINQ Fundamentals 3.1. Introduction 3.2. Comparaison avec les tableau Array 3.3. GroupJoin 3.4. Select 3.5. OrderBy 3.6. GroupBy 3.7. Having 3.8. Linq-to-XML CHAPITRE 4 - .Net Core 4.1. C'est quoi Asp.Net Core 4.2. Asp.Net Core au plus simple 4.3. Asp.Net Core au plus simple API 4.4. Asp Dot Net Core MVC avec Entity Framework 4.5. EntityFramework 4.6. Deployer une application ASP.NET 4.7. Migrer de ASP.NET Core 2.2 à 3.0 CHAPITRE 5 - Fiches, Composants et ressources. 5.1. Communication entre les controles 5.2. Traitement asynchrone sur les controles 5.3. Utilisation des evenement Background 5.4. Utilisation des threads CHAPITRE 6 - Gestionnaires de contenus CMS 6.1. Orchard CMS
Le langage C# est un langage intermédiaire entre le puissant mais compliqué C++ et le facile mais limité Visual Basic. Un fichier C# porte l'extension .CS.
C# est :
Souple : Un programme C# peut être exécuté sur la machine sur laquelle il se trouve ou bien transmis par l'intermédiaire du Web pour être exécuté sur un ordinateur distant.
Puissant : C# dispose essentiellement du même jeu d'instructions que C++, mais avec les angles arrondis.
Facile à utiliser: Dans C#, les commandes responsables de la plupart des erreurs ont été modifiées pour les rendre plus sure.
Visuel : La bibliothèque de C# fournit les outils pour créer directement des fenêtres d'affichage élaborées.
Prêt pour Internet : C# est le pivot de la nouvelle stratégie Internet de Microsoft, nommée .NET (prononcer point net).
Sûr: Tout langage destiné à une utilisation sur Internet doit contenir sous une forme ou sous une autre des outils de sécurité pour se protéger contre les hackers.
Enfin, C# est une partie intégrante de .NET.
Qu'est-ce que .NET ?
. NET est la stratégie adoptée par Microsoft dans le but d'ouvrir le Web aux
simples mortels comme vous et moi.
Il est difficile de programmer pour Internet dans des langages comme C ou C++.
Sun Microsystems a répondu à ce problème en créant le langage Java. Celui-ci
repose sur la syntaxe de C++, rendue un peu plus accessible, et est centré sur
le principe d'un développement distribué.
1) Paramétrer les exclusion de Windows Defender:
Exclure les processus:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\ - Web\External\node.exe C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\ - IDE\devenv.exe - ServiceHub\Hosts\ServiceHub.Host.Node.x86\ServiceHub.Host.Node.x86.exe C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe C:\Program Files\dotnet\dotnet.exe C:\Program Files\nodejs\node.exe sqlservr.exe, iisexpress.exe, iisexpresstray.exe
Exclure les dossiers:
// Dossiers des projets D:\sources // visual studio & tools C:\Program Files (x86)\Microsoft Visual Studio 10.0 C:\Program Files (x86)\Microsoft Visual Studio 14.0 C:\Program Files (x86)\Microsoft Visual Studio C:\Windows\assembly C:\Windows\Microsoft.NET C:\Program Files (x86)\MSBuild C:\Program Files\dotnet C:\Program Files (x86)\Microsoft SDKs C:\Program Files\Microsoft SDKs C:\Program Files (x86)\Common Files\Microsoft Shared\MSEnv C:\Program Files (x86)\Microsoft Office C:\Program Files (x86)\IIS Express\iisexpress.exe C:\Program Files (x86)\IIS Express\iisexpresstray.exe // cache folders C:\ProgramData\Microsoft\VisualStudio\Packages C:\Program Files (x86)\Microsoft SDKs\NuGetPackages C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files C:\Users\USERNAME\AppData\Local\Microsoft\VisualStudio C:\Users\USERNAME\AppData\Local\Microsoft\WebsiteCache C:\Users\USERNAME\AppData\Local\Jetbrains C:\Users\USERNAME\AppData\Roaming\Microsoft\VisualStudio C:\Users\USERNAME\AppData\Roaming\JetBrains C:\Users\USERNAME\AppData\Roaming\npm C:\Users\USERNAME\AppData\Roaming\npm-cache
2) Configurer Visual Studio
Vous trouverez ci-dessous une liste de paramètres recommandés pour améliorer la réactivité de l'interface utilisateur et les performances de l'environnement, en fonction des meilleures pratiques.
Environment -> General Uncheck “Automatically adjust visual experience based on client performance” Uncheck “Enable rich client visual experience” Check “Use hardware graphics acceleration if available” Environment -> AutoRecover Uncheck “Save AutoRecover information every” Environment -> Documents Check “Save documents as Unicode when data cannot be saved in codepage” Environment -> Startup Uncheck “Download content every” Environment -> Synchronized settings Uncheck “Synchronize settings across devices when signed into Visual Studio” Projects and Solutions Uncheck “Track active item in solution explorer” Check “Lightweight solution load for all solutions” Projects and Solutions -> Build and Run Check “Only build startup projects and dependencies on run” Projects and Solutions -> Web Package Management Set “Restore on Project Open” to false (for Bower) Set “Restore on Save” to false (for Bower) Set “Restore on Project Open” to false (for NPM) Set “Restore on Save” to false (for NPM) Text Editor -> C# -> Advanced Uncheck “Enable full solution analysis” Text Editor -> JavaScript/TypeScript -> EsLint Set “Enable ESLint” to false Debugging Uncheck “Suppress JIT optimization on module load (Managed only)” Uncheck “Enable Edit and Continue” Debugging -> Just-In-Time Uncheck “Script” IntelliTrace Uncheck “Enable IntelliTrace” Node.js Tools Set “Check for surveys/news” to “Never”
3) Désactiver les extensions
4) Charger tous les symboles
réf:
https://medium.com/burak-tasci/tweaking-the-environment-to-speed-up-visual-studio-79cd1920fed9
Dans Visual Studio on peut déboguer le C# et le javascript en mettant des points d'arrêts. On peut les exporter et les importer selon les modules à déboguer. Attention les points d'arrêt qui s'étendent sur trop de lignes, peuvent bloquer l'importation. Les points d'arrêts sont paramétrables avec des étiquettes, des conditions d'arrêt et des traces. Il est ensuite facile de faire des recherches dessus, dans le champ de recherche du panneau "points d'arrêt" (icône >>). Cela permet de pouvoir supprimer ou activer les points selon leur étiquette(s).
Si un point d'arrêt n'est pas lié c'est soit :
Pour déboguer :
Les packages s'installent dans le sous dossier "packages". Et les dépendences sont inscrites dans le projet. Pour recréer le dossier "packages", (à la manière de npm install), il faut aller dans la Console du Gestionnaire de package, et taper "Update-Package". Cependant sur les gros projet je conseille de conserver ce dossier dans le cas ou certaines dépendence ne sont pas à jour.
Lors de la mise à jour des packages, si vous avez une erreur The length of the full path for the solution... exceeds the maximum path length Cette erreur est due à un bug du gestionnaire de packages dans Vis Stu 2017, qui cherche des références contenus dans des dossiers inutilisés. Aller dans Générer Nettoyer la solution. Cela supprimera tous les dossiers obj et bin.
Lors de la mise à jour des packages, si vous avez une erreur SSL
update-package : Impossible de charger l'index de service pour la source
https://dotnet.myget.org/F/dotnet-core
.
aller sur https://www.ssllabs.com/ssltest pour vérifier la validité du package. pour dotnet.myget.org, il a été retiré fin 2020. Supprimer le fichier de config NuGet.config de la solution qui fait référence à dotnet.myget.org
Cela peut provenir d'un problème de proxy. Dans ce cas accédez à l'emplacement d'installation de Visual Studio C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE Ouvrez le fichier devenv.exe.config Ajouter defaultProxy tags comme ci-dessous, dans la balise system.net existante -
Lors de la compilation si vous avez une erreur de Dll manquande
Quand c'est une DLL d'un de vos projet, il faut vérifier l'ordre de compilation
des projets, Parfois ça fonctionne à la deuxième construction. Si ça bloque
encore sur une dll manquante d'un de vos projet dont la construction ne s'est
pas faite. Aller sur le projet dont la dll est manquante (Sélectionner le projet
dans l'explorateur de solution, ou définir comme projet de demarrage), et faire
Générer, Regénérer
En cas d'erreur de syntaxe en rapport avec des changements de version de package Par exemple, un code source écrit avec Automapper v6.1.1, aura des erreurs de compilation avec la v10.0.0 : 'ISourceMemberConfigurationExpression' ne contient pas de définition pour 'Ignore'
Dans ce cas il faut bien vérifier la référence au niveau du projet, voir les propriétés de la référence à AutoMapper, notamment la version, et éventuellement supprimer la mauvaise dll dans l'emplaceent indiqué.
C# definit les caractères d'échappements suivants:
\' – simple cote \" – double cote \\ – backslash \0 – Unicode character 0 \a – Alert (character 7) \b – Backspace (character 8) \f – Form feed (character 12) \n – New line (character 10) \r – Carriage return (character 13) \t – Horizontal tab (character 9) \v – Vertical quote (character 11) \uxxxx – Unicode escape sequence for character with hex value xxxx \xn[n][n][n] – Unicode escape sequence for character with hex value nnnn (variable length version of \uxxxx) \Uxxxxxxxx – Unicode escape sequence for character with hex value xxxxxxxx (for generating surrogates)
Compilation: C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc hollo.cs
Ajouter des paramétres d'exécution: Dans l'explorateur de solutions Click droit HelloWord Propriétés, Déboguer
Ajouter des paramétres d'exécution: Dans l'explorateur de solutions Click droit HelloWord Propriétés, Déboguer
Pourquoi la p.o.o (Programmation Oriente Objet)?
Pour la modularite: modules independant les uns des autres. Pour la maintenabilite et la reutilisabilite. L'objectif est de reutiliser le maximum d'objets existant.
attribut: ensemble de variables qui constituent les donnees de la classe. methode: ensemble des fonctions qui constituent les traitements de la classe classe: une classe est un type d'objet qui regroupe attributs et methodes. objet: un objet est l'integration d'une classe. instance: variable qui a été déclarée du type d'une classe. encapsulation: regroupement des donnees dans un objet pour masquer les attributs interphace: vue externe de l'objet (prototype des differentes methodes) accesseurs: methodes qui renvoient ou qui modifie la valeur d'un attribut.
ex: objet voiture donnees: vitesse, couleur, marque, annee, ... traitement: se deplacer, prendre de l'essence, s'user, ... voiture r5,r21,mustang; r5,r21 et mustang sont des instances de l'obet voiture.
cette methode permet d'éviter que des variables soient modifiées n' importe ou, et intempestivement.
ex: r5.annee=1976; // pas bon r5.setannee(1976); // bon: principe d'encapsulation Si l'attribut annee change de nom dans la classe, on aura pas a modifier tout le programme. L'encapsulation n'est pas obligatoire en c#, c'est au programmeur de faire attention.
En informatique et en théorie des types, le polymorphisme, est le concept consistant à fournir une interface unique à des entités pouvant avoir différents types.
L’opérateur is vérifie si le résultat d’une expression est compatible avec un type donné, ou (à compter de C# 7. 0) teste une expression par rapport à un modèle. À compter de C# 7. 0, les instructions is et switch prennent en charge les critères spéciaux. Le mot clé is prend en charge les modèles suivants :
public int CompareTo(Object o) { var e = o as Employee; if (e == null) { throw new ArgumentException( "o is not an Employee object."); } return Name.CompareTo(e.Name); |
Modèle de constante : teste si une expression correspond à une valeur de constante spécifiée. Ex: if (o is null)
Modèle de variable : correspondance qui réussit toujours et lie la valeur d’une expression à une variable locale.
Ajouter une classe: Dans l'explorateur de solutions Click droit Grades Ajouter, Classe... Sélectionner classe et nomer la classe. Pour créer une constructor automatiquement taper ctor et double Tab Pour créer un console.write automatiquement taper le snippet cw et double Tab
La variable book contient une adresse vers l'emplacement mémoire ou est stockée l'instance de objet/classe de type GradeBook. Elle peut pointer à tout objet de GradeBook dont je dispose, ainsi lors de la 2eme affectation, l'accès à la 1ère instance est perdue. L'instance perdue est détruite par le garbage collector.
Le mot clé public, devant la déclaration de la liste de grades, permet un accès direct à cette variable sans passer par la méthode ex: book.grade.Add(87); Avec private la variable grade est encapsulée dans la classe; elle ne sera accéssible qu'au travers du modifier AddGrade ex: book.AddGrade(87);
Le parcours d'une list se fait par foreach(float grade in grades)
En c# les classes systèmes possèdent des méthodes d'aide, par ex, Float possède la méthode MaxValue ex: Float.MaxValue. Les méthodes d'aide ne modifient pas la valeur de la variable. Ex: name = name.ToUpper(); et nom name.ToUpper(); La touche F12 permet d'ouvrir la source de la classe qui est sous le curseur.
Lorsque deux classes entrent en interaction, un couplage se crée. Il existe une technique permettant de limiter l’impact de ce couplage sur la maintenabilité du code. Il s’agit de l’injection de dépendance.
L’injection de dépendance permet d’établir de façon dynamique une relation entre les classes. Elle permet ainsi de découpler les éléments les uns des autres et de ne plus décrire explicitement leurs relations dans le code. De ce fait, elle facilite la modification ultérieure du code, et l’ajout de nouvelles fonction- nalités.
La classe Car ne reçoit plus l’objet spécifique steeringWheel mais un objet respectant le contrat (interface) ISteeringWheel (qui implémente les contraintes d’un volant). Dorénavant, quand notre voiture aura besoin d’un volant qui contient un klaxon, il suffira de ne plus lui donner l’objet steeringWheel mais l’ objet steeringWheelwithklaxon. Le comportement du volant reste inchangé pour la voiture. Quant au klaxon, il ne sait pas que le bouton le déclenchant est aussi un volant. Dans le découplage des éléments, les objets ne doivent pas savoir avec qui ils interagissent, quelles sont leurs caractéristiques spécifiques respectives, ni même qui les appelle.
steeringWheelWithKlaxon peut donc respecter les contrats ISteeringWheel (précédemment défini) ainsi que IKlaxon:
Lors de chaque création d'une instance, les attributs, et les pointeurs sur les méthodes sont recopiées en mémoire. Ainsi chacune des instance contient ses propres attributs. Le fait de déclarer un attribut 'statique' peut permettre à toutes les instances de partager la meme donnée. La donnée peut être lue sans instancier la classe ex: GradeBook.MaximumGrade
Pour Ajouter une référence, clic droit sur Références dans l'explorateur de solutions, Ajouter une référence. Vous pouvez faire une rechercher sur le nom. ex: SpeechSynthesizer. La référence s'ajoute à la liste de références.
L'explorateur d'objets permet de voir les classes système, avec leur méthodes. Pour afficher une référence dans l'explorateur d'objets, click droit, Afficher dans l'explorateur d'objets. On voit la liste des classes importable avec using, ainsi que les méthodes utilisables.
Consiste à écrire un test pour tester un code. Click droit dans l'explorateur de solutions, sur le projet en cours, Ajouter, Nouveau projet, Test, Application de tests unitaires. Nommer le projet ex: Grades.Tests. Ajouter une commande de test dans TestMethod1, ex: Assert.AreEqual(3, 3); Maintenant, dans le menu Test de VisualStudio, il est possible d'exécuter tous les tests.
Supprimer l'unité générée UnitTest1, et recréer une classe ex: "GradeBookTests" Taper [TestClass] au dessus de la classe, correction éventuelles, cliquer sur Microsoft.VisualStudio.TestTools.UnitTesting.
Ajouter une Assemblée dans les références du projet de test, choisir projets, solution, Nommer l'unitée Grades. Au besoin utiliser l'attribut "internal" au lieu de "private" pour pouvoir accéder à la propriété de la classe depuis la classe de test. Ajouter "public" devant class GradeBook et GradeBookTests.
Accesseurs:
Iteration:
Condition:
Cela se fait par le mot clé ref
Le mot clé out entraîne le passage des arguments par référence. Il fait du paramètre formel un alias de l’argument, qui doit être une variable. En d’autres termes, toute opération portant sur le paramètre est effectuée sur l’argument. Il est similaire au mot clé ref, à la différence que ref nécessite que la variable soit initialisée avant d’être passée. Il est également similaire au mot clé in, à la différence que in n’autorise pas la méthode appelée à modifier la valeur d’argument. Pour utiliser un paramètre out,
les éléments ignorés, qui sont des variables d’espace réservé qui sont intentionnellement inutilisées dans le code de l’application. Les éléments ignorés sont équivalents à des variables non affectées : elles n’ont pas de valeur. Les éléments ignorés sont particulièrement utiles pour travailler avec des tuples quand le code de votre application utilise certains éléments d’un tuple mais ignore les autres. ex :
Le compilateur fait la difference entre fonctions, par le nom, le nombre d'arguments, les types des arguments. Le type retourne n'est pas pris en compte.
S'il existe une fonction surdefinite sans parametres, l'appel de cette fonction peut se faire de 2 maniere distinctes; avec ou sans parentheses. Dans ce cas, il ne doit pas y avoir une fonction avec que des parametres par defaut, car la distinction n'est pas possible. Il est possible de caster (modifier le type) les paramètre avec cette syntaxe: fct((int)aa);
Un delegate est un type référence qui peut être utilisé pour encapsuler une méthode anonyme ou nommée. Les délégués sont comparables aux pointeurs fonction en C++, mais ils offrent l’avantage d’être sûrs et de type sécurisé. Les délégués sont la base des événements.
Depuis visual studio, créer une classe NameChangedDelegate,
Adaptation pour une classe Args :
Si throw est exécuté dans un bloc try (depuis une fonction), les clauses catch associées à ce bloc sont examinées pour voir si l'une d'elles peut gérer l'exception. Si une clause catch est détectée, l'exception est gérée. Si aucune clause catch n'est détectée, la recherche se propage dans les bloc try-catch de niveau supérieur. Si aucun gestionnaire n'est trouvé, le programme appelle la fonction terminate() définie dans la bibliothèque du C++ standard. Cette fonction appelle abort() qui indique "Abnormal program termination".
Inheritance:
Polymorphism:
virtual: methode de la classe de base pouvant être surdéfinie.
Une classe abstraite, est une méthode qui ne peut pas être instanciée.
Une méthode abstraite, est une méthode qui doit être obligatoirement surchargée.
Elle se déclare avec Abstract. Ainsi il est possible de travailler sur tous les
types de sous classes, depuis le type classe de base, au travers des méthodes
abstraites qui sont forcément existantes. Les méthodes virtual, traitent le type
spécifique de la la sous classe ex: Chien : Animal, Chien.cours Chat.cours
List
Une interface peut être instanciée, elles sont plus flexibles que les classes abstraites. C# permet de mettre en oeuvre plusieurs interfaces sur un type.
Tous les objets .NET de l'interface IEquatable, contiennent une méthode Equals
qui peut être surdéfinie.
Equals prend en paramètre un type Object, qui n'est pas fortement typé. Pour
surdéfinir Equals avec un type plus sure, il faut utiliser IEquatable
Par convention, une classe concrete est dérivée d'une interface, et possède les propriétés et méthodes concrettes (ex: rectangle carré qui dérivent de polygon). Par convention le nom d'une interface commence par un "I" ex: ConcreteRegularPolygon -> IRegularPolygon
Par le principe de ségrégation, seules les interfaces utilisées par le client sont implémentées. L'héritage d'interface permet d'ajouter des fonctionnalités à une interface existante sans casser le code. ex: public interface ISaveable { string Save(); } public interface INamedSaveable : ISaveable { string Save(string name); }
La différence principale entre les interfaces, et les classes abstraites est que certaines méthodes de la classe abstraite sont obligatoirements surchargées, alors que dans une interface elles ne le sont pas forcément (cas des méthodes définient en virtual dans l'interface).
Les classes abstraites peuvent contenir du code de mise en oeuvre, alors les Interface ne le peuvent pas. En C#, nous avons un concept d'héritage unique, une classe ne peut hériter que d'une seule classe de base. Inversement, une classe peut implémenter n'importe quel nombre d'interfaces.
Les membres des classes abstraites peuvent avoir des access modifiers (public protected internal). Les membres pour les interfaces sont automatiquement public. Par défaut toutes les classes héritent de la classe Object.
Classes Abstraites : Fiels, Properties, Constructors, Method, Events, Indexers Interfaces : Properties, Methods, Events, Indexers
Bonne pratique: Programmer pour une abstraction, pas pour un type concret.
Maintenabilité: Les interfaces sont moins senssibles aux changements, car on ne soucis pas du détail d'un objet mais uniquement d'une ou plusieurs propriétés, ou d'un type de donnée ex List IEnumerable, une modification d'une sortie de Array en List dans l'interface ne chanche pas l'utilisation via IEnumerable.
Classes abstraites avec une implémentation partagée: Les classes MembershipProvider et RoleProvider dans ASP.NET sont utilisés pour gérer la sécurité.
Il existe un grand nombre d'interfaces qui sont conçus pour ajouter des morceaux de fonctionnalité à des classes existantes:
Base Classes qui implémentent une classe abstraite (car le code très différents)
Il est possible de redefinir les operateurs =, +, -, *, /, == pour une classe.
Il est importatnt dans ce cas, de redéfinir à l'identique Equals et ==, pour ce
même type. Pour comparrer une référence il vaux mieux utiliser ReferenceEquals.
De même il faut redéfinir != NotEquals et GetHashCode
En effet == sur un objet retourne toujours une référence, mais peut être sur
définie dans d'autres classes.
La sur définition d'opérateur n'est pas possible avec un type générique T
ex: static void Display
Dans une sous classe qui se distingue par une méthode supplémentaire:
Il est possible d'empêcher une classe d'être dérivée, grâce au mot-clé sealed. Pour masquer une méthode (ou une variable), on utilisera le mot-clé new devant cette méthode (ou variable). Il est préférable d'utiliser les interfaces IEquatable, IComparable, et IComparer dans une classe scéllé. En effet la classe de base ne connais pas les propriétés supplémentaires des classes dérivés. et ignoreras les champs supplémentaires dans les types dérivés.
Les comparer permettent de créer plusieurs compareurs (classes) pour un Type, il
en existe plusieurs: IComparer, IEqualityCompareur
Un hashSet est une liste d'éléments uniques. A chaque addition dans la liste, le
HashSet test l'égalité. Il faut créer une classe :EqualityCompareur avec une
méthode override int GetHashCode si on veut modifier l'égalitée naturelle.
var foodItems = new HashSet
3 familles de collections: Lists, Dictionaries, Sets Les dictionnaires vous permettre d'utiliser n'importe quel type pour la clé, des entiers, des dates, des chaines, ou des classes personnalisées. Les Sets permettent de faire une intersection ou un DISTINCT UNION en SQL entre deux collections, comme les dictionnaires ils sont basé sur une table de hachage mais n'ont pas de clé. Ils ne sont pas destinés a effectuer une recherche mais de fournir l'ensemble des enumérations.
C# implémente beaucoup de classes de collection :
comparateur personnalisé:
StringBuilder permet de concatener des chaines de caractère de façon très rapide Mais attention a la consommation de mémoire. En cas d'utilisation répété et avec beaucoup de données il faudra réutliser le stringBuilder.
réf: StringBuilder with Caching
https://stackoverflow.com/questions/45968920/stringbuilder-with-caching-threadstatic
Avant tout, il est possible d'installer le SDK .Net, pour avoir la doc des APIs, les exemples (ex pour signalR), et pour accéder au code source. Pour cela il faut d'abord installer dotnet-sdk-2.1.3-win-x64.exe, puis dans Visual Studio, il faut cloner
Les documentations .Net sont open source. Elles sont crées au format markdown. Le format markdown permet également de générer des fichier HTML, CHM ou pdf.
Toutes les documentations
https://docs.microsoft.com/fr-fr/documentation/
.Net (source Markdown, site, pdf):
https://github.com/dotnet/docs.fr-fr
https://docs.microsoft.com/fr-fr/dotnet/core/tools/project-json-to-csproj
https://docs.microsoft.com/fr-fr/dotnet/opbuildpdf/fundamentals/toc.pdf?branch=live
C Sharp (source Markdown, site, pdf):
https://github.com/dotnet/docs.fr-fr/tree/live/docs/csharp
https://docs.microsoft.com/fr-fr/dotnet/csharp/
https://docs.microsoft.com/fr-fr/dotnet/opbuildpdf/csharp/toc.pdf?branch=live
.Net Core (source Markdown, site, pdf):
https://github.com/dotnet/AspNetCore.Docs.fr-fr
https://docs.microsoft.com/fr-fr/aspnet/core/blazor/?view=aspnetcore-5.0
https://docs.microsoft.com/fr-fr/dotnet/opbuildpdf/csharp/toc.pdf?branch=live
Entity Framework (source Markdown, site, pdf):
https://github.com/dotnet/EntityFramework.Docs.fr-fr
https://docs.microsoft.com/fr-fr/ef/efcore-and-ef6/
https://docs.microsoft.com/fr-fr/ef/opbuildpdf/toc.pdf?branch=live
Télécharger le fichier docfx.zip depuis https://github.com/dotnet/docfx/releases
et le décompresser dans "C:\Program Files\docFx". Ajouter le chemin dans le PATH
pour pouvoir l'exécuter n'importe où. Pour générer la documentation en html dans
le sous dossier "_site", éxécuter la commande suivante:
C:\> docfx aspnetcore\docfx.json --serve
Ensuite pour générer la documentation en chm le mieux est d'utiliser WinCHM Pro. Aller dans le dossier "_site\styles", et supprimer tous les fichiers ".js". Faire nouveau projet, Create a project using existing html files et sélectionner le dossier "_site". WinCHM vat générer le sommaire à partir des pages. Il est possible de le modifier, par exemple de déplacer les dossiers à la racine, etc. En cliquant sur un élément du sommaire, dans l'onglet "Topic options", on peut ajouter des mots clés pour la création d'un index.
Dans Projet, "Propriétés de ...", Build, cocher "Fichier de documentation XML". Utiliser > et < pour mettre les caractères > et < .
Ces tags sont utilisables en fonction de l'entité documentée
Entité Tags utilisables |
class struct interface delegate enum event constructor property method <summary>, <remarks>, <seealso> <summary>, <remarks>, <seealso> <summary>, <remarks>, <seealso> <summary>, <remarks>, <seealso>, <param>, <returns> <summary>, <remarks>, <seealso> <summary>, <remarks>, <seealso> <summary>, <remarks>, <seealso>, <param>, <permission>, <exception> <summary>, <remarks>, <seealso>, <value>, <permission>, <exception> <summary>, <remarks>, <seealso>, <param>, <returns>, <permission>, <exception> |
Description des Tags:
Tag Description |
<c> <code> <example> <exception> <list> <para> affiche le texte qu'il contient sous la forme de code. affiche le texte sous la forme de code en multiligne. fournit un exemple d'utilisation de l'entité. fournit des infos sur la levée d'une exception par une méthode. crée une liste d'élément avec puce, numéroté ou en tableau. crée un paragraphe à l'intérieur d'un tag. |
Exemple de description:
Génération de la documentation au format Web
GhostDoc est une extension gratuite pour Visual Studio. Il permet de générer la documentation complète de l'ensemble de la solution. Cependant il produit un chm incomplet. Mais il est possible de reconstituer un document valide à partir des fichiers temporaires (%TEMP%\SubMain.GhostDoc`1). Voici la procédure:
Dans Visual Studio, faire Outils, GhostDog, Build Help Documentation
Installer HTMLhelp workshop lancer hh -decompile Destdir Source.chm sur le chm généré
Récupérer les fichiers manquant depuis le dossier temporaire suivant: %TEMP%\SubMain.GhostDoc`1
.\icons\ .\scripts\ .\Styles\ xxx.hhp
Créer un fichier .hhp pour qu'il corresponde aux fichiers générés .hhc et .hhk
Source.hhp :
Lancer htmlHelpWorkshop et ouvrir le projet Source.hhp et faire: File -> Compile Un nouveau fichier chm est généré. Il est possible de l'ouvrir avec lhelp.exe
Il est possible d'automatiser la génération avec hhc.exe contenu dans le dossier d'installation de HTMLhelp workshop "%ProgramFiles(x86)%\HTML Help Workshop\hhc" Source.hhp
réf: documentation du code en c#
https://www.jmdoudoux.fr/microsoft/doctechcsharp/doctechcsharp.htm
Ces closses implémentent les méthodes suivantes: WriteLine, WriteLineIf, Indent, Unindent, Assert, Flush
Lors de l'execution en mode débug, on peut afficher les outils de diagnostic qui donneront la consommation mémoire et processeur du processus. Menu Déboguers, Fenêtres, Afficher les Outils de Diagnostic.
Accès à IIS Express depuis l’extérieur
première chose : lancez votre projet et regardez l’URL, où de vous rendre dans les propriétés de votre projet onglet « Web » où vous trouverez l’URL du projet avec son port. Fermez Visual Studio et vérifiez que IIS Express ne s’exécute plus.
Dans le pare-feu de Windows (si ce dernier est actif) ajouter une règle entrante autorisant le port du site web. Vous pouvez également dans un invité de commande en mode administrateur, exécuter la commande (sur une seule ligne):
Autoriser l'écoute de votre adresse IP et port
Attention à bien saisir l’adresse IP avec le port. De même pour la partie «user» il s’agit du groupe autorisé, en anglais le groupe se nomme « Everyone »
Modifier le fichier « $(solutiondir).vs\config\applicationhost.config » pour avoir ceci :
A partir de maintenant IIS Express et donc Visual Studio, necessitent des droits Administrateur lancer le serveur.
Relancez Visual Studio, et exécutez votre projet. Dans la systray (zone d'icône a coté de l'horloge) se trouve une icône "IIS Express", faire un clic-droit et sélectionner le menu "Afficher toutes les applications". Vous devez voir apparaître votre site deux fois ; une avec le localhost et l'autre avec votre adresse IP.
Pour revenir à l'état initial supprimer la règle IISExpressWeb au niveau du pare feux, et exécuter en tanq qu'administrateur :
Accès à IIS Local
Dans certains cas il peut être utile de simuler le fonctionnement sur le serveur de production sans passer par IISExpress, et sur un port spécifique. Pour cela vous devez modifier le fichier csproj en remplaçant ceci :
par cela :
Netoyage des fichiers temporaires chrome
Après quelques mois de deboguage intenssif certains dossiers temporaire de
chrome peuvent grossir enormément. Dans ce cas vous pourrez faire le ménage dans
le dossier suivant : et voir le téléchargement avec chrome://download-internals/
réf: Accès à IIS Express depuis l’extérieur
http://blog.ygrenier.com/2014/06/acces-iis-express-external/
Il existe différentes sources de données SGBDR, CSV, Web Services, Cloud. L'application n'a pas besoin de savoir comment accéder aux données ou comment faire des appels de webservice. Alors on crée une couche entre l'application et les données. Le Repository pattern: couche utilisant les interfaces/ collection pour accéder aux objets du domaine. Il s'agit de notre référentiel. Nous pouvons alors créer des implémentations différentes du référentiel qui adhèrent au contrat. pour créer des référentiels supplémentairess, il suffit d'adhérer à l'interface et tout fonctionne automatiquement. Ceux-ci sont souvent désignés comme les opérations CRUD (Créate, Read, Update, Delete).
En C# il est possible de surcharger les fonctions avec différents paramètres, mais nous n'avons pas le droit à des méthodes de surcharge en fonction du type de retour seulement.
Dossier References Add Service Reference, Discover, sélectionner PersonService.svc Nommer le service, aller dans Advanced Modifier le Collection type: System.Collections.Generic.List Renommer Class1.cs en ServiceRepository.cs et modifier la classe pour implémenter l'interface IPersonRepository
Dossier Repositories Add Existing Project
Application ViewModel Repository DataStorage
Le but du test unitaire est de tester de petites parties de code pour être sûr qu'une foie assemblés les différentes parties de code fonctionnent bien ensemble. Les parties de code qui interagissent avec l'interface utilisateur compliquent la réalisation des tests unitaire puiqu'il faut créer des object fenêttre, arguments, etc. qui ne sont pas forcement utilisés. Il vau mieux réaliser une séparation entre le code et l'interface graphique (viewModel)
1) Isoler l'interface utilisateur en utilisant le dataBinding 2) Créer des FakeRepository qu'on peut utiliser pour les tests.
PeopleViewer.exe.config Il suffit de décommenter ceci pour changer de repository et de DLL
Il existe différents types d'injection: - Constructor injection, Property Injection, Method injection, Service Locator Il existe plusieur containeur de dependency injection: - Unity, StructureMap, Autofac, Ninject, Castle Windsor, etc.
Utilisation de Service Locator: notre classe demande un service, notre SimpleContainer, pour localiser une instance d'un type particulier que cette classe a besoin.
App.config:
Ainsi le programme recherche le type dans le fichier de configuration, et charge cette assemblée en utilisant la réflexion, et crée effectivement cette instance. La différence est notre clé. Au lieu d'avoir notre PersonRepository clé, notre clé est le typeName complet. Notre conteneur peut analyser cette clé à partir de ce type générique que nous lui passons.
Mocking permet de créer des objets de l'espace réservé. Avec ces objets, pas besoin de mettre en oeuvre toute la classe, il suffit de fournir un comportement pour les méthodes que nous prévoyons d'utiliser.
Mocking Frameworks
Les méthodes d'extension permettent d'utiliser sa propre logique, dans une base de code externe. Visual Studio marque ces méthodes non native d'une flèche. ReSharper permet d'importer les namespaces. Utilisation de ildasm et dotPeek de JetBrains.
Déclaration d'une méthode d'extension. Le mot clé this permet d'étendre ce type.
Pour pouvoir utiliser notre méthode d'extension il faut ajouter using namespace; Une méthode d'extension peut être créée dans un espace de nom natif. Pour cela il faut créer un répertoire, et une classe que l'on rennome en l'espace de nom.
Il est également possible d'étendre les interfaces et les collections:
Il est également possible d'étendre n'importe quoi de n'importe quel type.
Advanced Extension Methods
Contournement pour les classes scéllés, méthode dangereuse si modification le la classe native. Problèmes de garbage collector, pas toujours implémentable sur les classe qui n'implémentent pas IDisposable.
Cette derniere methode rencontre un problème de vitesse à cause du temps d'accés avec le nom, ou si le déveoppeur change le nom de la propriété ex class Instrumentation private var _startedAt -> startedAt Mais il est possible d'utiliser un id
On ne peut pas étendre les types imbriqués (ex sous classe privé) AssemblyInfo.cs: permet d'acceder aux sous classes internal [assembly: InternalsVisibleTo("namespace")]
Il est possible d'utiliser les méthodes d'extension dans un autre environnemant en créant un "Portable Class Library". Créer une classe d'extension comme avant.
Si on change la cible en ".NET Framework 3.5 Client Profile" par ex. , il n'est plus possible d'ajouter la référence de la classe de méthode étendue portable, car le projet en cours ne supporte pas les références aux librairies portable. Pour palier à ce problème il suffit d'ajouter un lien: Créer un nouveau projet et ajouter la classe de la méthode d'extension en sélectionnant "Add as Link".
Sur les methodes d'extensions de comparaison, et est vaut mieux utiliser un type IComparable pour avoir une erreur du compilateur.
Extension Method Library
Installation des bibliothèques et des scripts clients :
https://docs.microsoft.com/en-us/aspnet/signalr/overview/getting-started/tutorial-getting-started-with-signalr-and-mvc
SignalR Client
https://docs.microsoft.com/en-us/aspnet/core/signalr/javascript-client?view=aspnetcore-2.1
La plupart des requêtes dans la documentation LINQ (Language Integrated Query) d’introduction sont écrites à l’aide de la syntaxe de requête déclarative LINQ. Toutefois, la syntaxe de requête doit être traduite en appels de méthode pour le Common Langage Runtime (CLR) . NET lorsque le code est compilé. Ces appels de méthode appellent les opérateurs de requête standard, qui ont des noms tels que Where, Select, GroupBy, Join, Max et Average. Vous pouvez les appeler directement en utilisant la syntaxe de méthode à la place de la syntaxe de requête.
Tableau d'objets: object[] objArray = new object[3];
Le type Array et covariant, ex: object[] objArr2 = daysOfWeek; objArr2[0] = 3;
Array.CopyTo .Reverse, .Sort IComparer
ICollection
IList
IDictionary
ISet
Une classe avec des propriétés publiques, est considérée comme un objet:
ex: var custs = new List
filtrer un dataSouce avec linq
IEnumerable
transformer un dataSouce avec linq var leader = from l in result.CatalogResponse where (l.ManufacturerCode == "BBG") select new { l.CountryCode, l.Date, l.Description, l.DistributorCode, l.ManufacturerCode }; dataGridView1.DataSource = leader.ToArray();
Dans le cas d'une jointure sur une clé étrangère pour un relation 1-1, voici comment filtrer l'ensemble des résultats sur un critaire de la table étrangère.
réf: groupJoin
https://www.tutorialsteacher.com/linq/linq-joining-operator-groupjoin
Inner Join avec la syntaxe de requête
Si vous voulez toujours utiliser votre constructeur pour l'initialisation et non les propriétés (à des fins d'initialisation), énumérer la requête en appelant ToList() ou ToArray(), et ensuite utiliser Select(...). Ainsi, elle utilisera LINQ to Collections et la limitation de ne pas pouvoir appeler le constructeur avec des paramètres dans Select(...) disparaîtra. Erreur: "Only parameterless constructors and initializers are supported in LINQ to Entities"
Vous devrez effectuer le classement en mémoire puisqu'il n'existe aucun moyen de transmettre cette logique de classement à SQL. Vous pouvez le faire en utilisant AsEnumerable() pour changer le contexte d'une requête SQL à une requête en mémoire :
réf:
https://stackoverflow.com/questions/52107040/using-external-list-to-order-a-linq-query/52107381
persons.GroupBy(x => x.PersonId).Select(x => x) ou pour contrôler les doublons: persons.GroupBy(x => x.PersonId).Where(x => x.Count() > 1).Any(x => x)
Exemple pratique d'implementation GroupBy :
Pour concatener un champs lors d'un groupBy en Linq :
réf:
https://stackoverflow.com/questions/7325278/group-by-in-linq/7325306
réf: Linq with group by having count
https://stackoverflow.com/questions/2078736/linq-with-group-by-having-count
réf: https://stackoverflow.com/questions/6228315/convert-xml-to-datatable
https://stackoverflow.com/questions/6228315/convert-xml-to-datatable
Créer une nouvelle "Application web (.Net Framework)", avec le modèle MVC. Aller dans "Extensions", "Gérer les extensions". Sur la gauche cliquer, "En ligne", et rechercher "productivity power tools". Un autre pluggin est "web essentials". En payant il y ReSharper aussi.
Visual Studio Online, est gratuit pour un maximum de 5 utilisateurs. Lancé en
2013, VS Online est un ensemble de services cloud pour les utilisateurs de VS
qui était auparavant connu sous le nom de Team Foundation Studio TFS. VS Online
permet aux équipes de dévs de coopérer sur des dépôts de code source privés
stockés dans le cloud. Il prend en charge des outils de gestion de projet tels
que les tableaux Kanban, et peut être utilisé avec VS, Eclipse, Xcode et
d'autres clients Git. Au-delà des 5 utilisateurs gratuits, le prix de base est
de 20 USD par utilisateur et par mois https://app.vssps.visualstudio.com/
Le demarrage d'un projet necessite, une étude préalable du cahier des charge et d'en déduire les différents cas d'usages (use cases), et leur dépendances. Par exemple un site pour suivre les artistes, avec une gestion de leur concerts. On souligne les cas d'usages principaux tel que: "Ajout de concert", les usages secondaires tel que suppression de concert, sont dans le meme domaine d'applicat ion que l'ajout. on définit un ordre d'implémentation, de prèférence permettant de montrer la fonctionnalité principale du début à la fin, cela permet de créer le skelette de l'application, et d'y rajoutter de nouvelles fonctionnalités.
Dans VS Online on vat créer un projet; saisir le nom un projet, puis dans avancé sélectionner le process Agile. Allez dans Backlogs et faire "+ New Work Item", pour ajoutter les user stories. Puis placez les stories dans les itérations selon l'ordre choisit.
Aller dans Outils, Gestionnaire de package NuGet. Selectionner le projet, et dans parcourir rechercher entityframework, et enfin cliquer sur Installer. Aller dans Outils, Gestionnaire de package NuGet, Console du Gestionnaire de package et taper enable-migrations. Si une erreur survient, installer la version 6.1.3 . Créer sous le dossier Models, une classe "MyDbContext" qui hérite de DbContext Puis relancer enable-migrations. VS vat créer un fichier "Configuration.cs" dans le dossier Migrations.
Installer le package NuGet "Microsoft.AspNet.Identity.EntityFramework.2.2.3" Installer le package NuGet "Microsoft.Owin"
CHAPITRE 4 - .Net
Asp.Net Core est la réponse à Node.js qui consiste à faire tourner du javascript coté serveur, qui a défrayé la chronique en montrant qu'en fait c'était le serveur le plus rapide de la planète, celui qui montait le plus en charge, et qui traitait le mieux les requêttes. En Node.js on a un ensemble de package pour référence et puis on avance avec npm
Asp.Net Core est open source multi plateformes, tout comme le feu projet rotor. c'est un re design de ASP dotnet, les équipes de production sont repartis pratiquement de zéro, pour s'enlever de quelque chose qui a 15 ans d'existance, et de pouvoir s'adapter du web d'aujourd'hui, c'est-à-dire léger flexible et qui est capable d'utiliser tous les framworks de dernière génération javascript. Il faut savoir que Asp.Net était basé sur "system.net.dll", qui est une dll qui fesait uniquement partie de windows. Aujourd'hui asp.net core s'est enlevée de ce système là, pour être complètement agnostique à la plateforme et fonctionne avec des packages nugets (qui est l'équivalent de npm).
Il faut savoir que la carte asp.net était devenue un poil trop lourde avec le temps. Initialement l'idée c'était qu'avec asp net web forms, de dire à des développeurs desktop du début des années 2000 : "ben voilà en utilisant les mêmes techno vous pouvez faire du web", et donc du coup ça veut dire que ça s'appuyait sur plein de librairies windows très grosse, il y avait toute la partie systeme.foms, systeme.xml, et ça avec le temps c'est devenu un handicap. Donc je pense que c'était vraiment absolument vital de repartir sur un truc très léger adapté au web d'aujourd'hui de manière à pouvoir enlever tous le legacy qui nous embêtent aujourd'hui, et avec lesquels on ne pourra pas avancer parce que il ya trop de choses qui sont basés dessus.
On ne croit plus à cette histoire de dire: "on a des enormes composants qu'on va coder comme des objets desktop et puis on ne fait pas attention qu'il y a le web entre les deux. Ces trucs là aujourd'hui les gens n'en veulent plus. Ils veulent quelque chose léger, et des choses en ligne de commande parce que c'est comme ça que ça fonctionne, parce que l'on a besoin de la ligne de commande, avec le coté devOps dans lequel on veut pouvoir automatiser les choses. Et puis on veut pouvoir déployer n'importe où, n'importe comment. Aujourd'hui avec la ligne de commande, on sépare complètement la partie serveur avec la partie front. Avec Asp.net web forms et même avec MVC, on tirait les framework javascript sous forme de paquets nugets, ce qui est un non sens. Pour faire du développement front il vaut mieux utiliser des outils front que de ramener des librairies. Par exemple: React, Angular, Vue, Knockout (issue du monde Microsoft)
ASP.NET Core prend en charge l’interface Open Web pour . NET (OWIN). OWIN permet que les applications web soient dissociées des serveurs web. Elle définit une façon standard d’utiliser un intergiciel (middleware) dans un pipeline pour gérer les requêtes et les réponses associées. Les applications ASP. NET Core et l’intergiciel peuvent interagir avec les applications OWIN, les serveurs et l’intergiciel. OWIN fournit une couche de dissociation qui permet à deux frameworks ayant des modèles d’objets distincts d’être utilisés ensemble. C'est comme ça qu'on peut avoir différents types de serveurs aujourd'hui; on a IIS, on a le http listener, on a Kestrel, et d'autres serveurs open source. et tous ces trucs là sont capables de communiquer avec x implémentation web donc à savoir; Asp net, mvc core bien sûr, mais aussi des framework open source comme Nancy ou d'autres choses derrière.
.Net Core contient:
VsCode est un fork de l'éditeur Atom de github. C'est un projet open source qui s'appelle OmniSharp qui apporte toute l'intellicence et toute l'intelligence à VSCose. Il fait parti maintenant de .Net fundation. C'est un petit serveur qui
va tourner en tâche de fond sur votre machine, et qui va analyser le répertoire de code de votre projet et qui va fournir toute l'analyse du code. L'intérêt de cette mécanique c'est que que l'on peut utiliser n'importe quel éditeur. Il suffit d'avoir un petit plugin dans l'éditeur qui est capable d'aller causer avec le petit serveur web. Donc maintenant on peut utiliser VSCode, Vim, Emacs, et avoir de l'intelicence, de la compilation d'un projet .Net Core.
On pourrait s'arrêter là, et dire on code tout notre application avec ça, aucun problème: tiens on demande la page d'accueil, je retourne le html avec un body.. Mais l'inconvénient c'est que ça va être inbitable. Le middleware MVC permet de faire ça. Tout ce que j'ai à faire c'est dans mon startup dire: je vais faire du mvc avec la commande app.useMvc().
Il s'agit d'une méthode d'extention qui est réellement codée dans le package MVC qui configure un middleware et son travail c'est de dire: puisqu'on va voir plein de requêtes entrantes on va essayer de découper un peu les choses et on va utiliser un modèle un pattern puisqu'on utilise souvent des patterns pour simplifier les grosses applications , et ce pattern c'est model view controller. MVC apporte également la testabilité, la répartition des rôles et une structure cliare et connue. L'inconvéniant est que ça rajoute de la complexité.
URL: Détermination de la route Action d'un (Méthode) Récupère les données à passer à la vue controleur: (classe) Si POST, traite les données remontantes Vue ou Json: Produit le HTML (Razor) ou du Json si c'est une webAPI
Dans Visual Studio faire New Project, "ASP.NET Core Web Application (.NETCore)". Puis Web Application car c'est le minimum pour générer des pages html. ou taper sur la console dotnet new mvc dans un dossier WebApplicationMUG. Bien qu'il soit encore possible d'utiliser l'ancien middleware UseMvc() ou UseRouter() dans une application 3.0, Microsoft recommande que chaque application migre vers Endpoint Routing si possible. Pour cela il faut plutot utiliser le modèle : "Application web (Model-View-Controller)" ou dotnet new mvc.
Le fichier le plus important de notre projet est sans aucun doute le fichier Startup.cs, il configure l’ensemble de l’application
Le fichier Program.cs, instancie un serveur web en quelque sorte et donne en paramètre le fichier Startup.cs (pour simplifier). C’est dans ce fichier que vous configurerez par exemple l’authentification, l’utilisation de session, l’utilisation de SignalR (websockets), l’utilisation d’identity (l’ensemble du mécanisme de connexion/inscription) et bien d’autre choses.
Le fichier *.csproj qui est le fichier du projet à proprement dit, il contient les références des paquets Nuget et c’est à peu près tout.
Quant aux fichiers appsettings.json (e t appsettings.Development.json), ils contiendront la configuration de votre application, comme par exemple des clés d’API ou les chaînes de connexion à votre base de données.
Maintenant toujours dans notre shell nous allons taper la commande dotnet run, .Net Core devrais télécharger quelques librairies et éxecuter notre projet, si vous avez un problème de certificat, c’est qu’il tante d’écouter en mode SSL, il faudra donc supprimer la ligne https://localhost:5001 dans launchSettings.json .
Quelques Commandes Utiles
Dans Views\Home on trouve les fichiers cshtml Dans Views\Shared on trouve les liens d'entête sont dans Shared Le pied de page avec la balise
Et donc quand on navigue sur Home/Index on tombe sur la vue dans Views\Home . Pour une "Web Application" classique non MVC dans Visual Studio 2019, le dossier des pages html est "Pages", et non plus "Views", par défaut le routage est fait plus en amont et avant l’exécution du middleware MVC dans le pipeline, il est effectué par un middleware spécial appelé “Endpoint Routing”. Ainsi, à partir d’ASP.NET Core 2.2 il faut désactiver le routage par point de terminaison pour que le routage s’effectue avec IRouter avec cette ligne dans Startup.cs:
On pourra ensuite personnaliser les routes dans la méthode Configure avec
Ou alors si le projet est créé directement avec "Application web ASP.NET Core", et le modèle Application web (Model-View-Controller) avec Visual Studio 2019, la route se fera ainsi (voir le chapitre 4.4):
Par défaut, il crée une vue Home avec du bootstrap. On a le fichier Views/Home/ Index.cshtml . Les liens d'entête sont référencé dans un dossier partagé Shared, dans _Layout.cshtml. Il contient l'appel @RenderBody() . On va créer un nouveau controller, MVCController, ex: MeetupsController, qui par défaut va chercher dans le dossier View\Meetups. Dans ce dossier créer un fichier index.cshtml
@{ ViewData["Title"] = "Index"; }
Bonjour les amis
Dans le dossier Controllers, click droit, Ajouter, contrôleur, contrôlleur MVC - vide. Le controlleur dit que quand on va demander la page Index, le controlleur va retourner la page vue qu'il va chercher par défaut dans le répertoire Meetups correspondant au nom de la classe.
Et on peut voir la vue en mettant /Meetups/Index dans l'url, après avoir lancé l'application. L'url, nous fait partir sur le controller MeetupsController et sur la vue qui va avec. Ici il serai possible d'aller chercher directement les prochains meetups dans la base de donnée, mais le code ne serai pas testable. Ce serai bien de dire donne moi les prochains meetups à la place. Et pour cela on va créer une interface. On créer un répertoire Services, et dedans on crée une interface IDataAccess qui sera responsable d'aller récupérer les données. Et dans cette interface je vais juste m'engager à avoir une méthode GetNextMeetup . La il faut lui créer un type, donc on crée dans le dossier Models la classe Meetup. Il me reste à décrire ce qu'est une classe meetup
Même si le service n'est pas implémenté, on peut le demander dans le contrôlleur
C'est comme ça qu'on code aujourd'hui, il s'agit d'injection de dépendance; on ne fait pas le boulot, mais on appelle le mec qui sait faire le boulot. Et donc cela fait du code lisible et du code testable, et au moment du test unitaire on peut injecter un faux, qui vat chercher des données en mémoire par exemple, et donc on est dans un environnement maitrisé. On peut aussi simplement demander le service en paramètre de la méthode Index, en y ajoutant un attribut devant qui est [FromServices], qui dit que ce IDataAccess vat être injecté dans cette méthode.
La méthode plus répandu est de demander ce IDataAccess dans le constructeur pour pouvoir y accéder partout. Créer un constructeur (ctor Tab Tab), ce qui donne :
Maintenant on peut générer la vue avec Visual Studio, en supprimant index.cshtml et en faisant un click droit sur le dossier Views/Meetups, Ajouter, Vue..., Vue Razor, nom de la vue: Index, Modèle: List, Classe de modèle: Meetup .
Maintenant on fait le boulot en créant une classe InMemoryDataAccess
Ensuite il faut indiquer à .NET Core, que quand on demandera un IDataAcces dans le cadre de cette application, c'est le InMemoryDataAccess qu'il faut utiliser. Cela se fait dans la méthode ConfigureServices de la classe Startup
services.AddTransient
Il y a aussi AddSingleton (instance unique), AddScoped (limité en temps), et il y a des surcharges inombrable qui permettent de dire que je peut lui donner une implementation factory. Voila le moteur d'injection fournis en natif avec . Net Core. Mais il n'est pas garanti fiable à 100% en production. Mais il permet de démarrer sans trop se casser la tête à trouver un moteur d'injection de dépendence comme unity par exemple.
réf: ASP.Net Core rooting
https://cdiese.fr/asp-net-core-routing/#routing-default_template
réf: .Net Core 2.2
https://www.youtube.com/watch?v=vcjj5pT0bSQ
réf: ASP.NET CORE Pourquoi ? Comment ? - MUG Montpellier #2
https://www.youtube.com/watch?v=z9Y8kENTMlc
réf: Débuter avec .Net Core (MVC)
https://medium.com/@clintnetwork/d%C3%A9buter-avec-net-core-mvc-938048c5feaa
réf: Comprendre le routage dans ASP.NET CORE
https://www.youtube.com/watch?v=0-_X9Ha7P4
réf: ASP.NET Core updates in .NET Core 3.0 Preview 4
https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-core-3-0-preview-4/
Ce qui a changé aussi par rapport à l'ASP. Net MVC qui n'était pas Core, c'est les webAPIs parce que de plus en plus aujourd'hui on a le fameux fullStack avec des trucs comme React, Angular, Vue, Knockout qui veulent du json. Et donc il ne faut pas leur retourner du html mais du json. Donc on peut supprimer toutes les vues. Cela se fait comme avec un contrôleur traditionnel. On vat rajouter un contrôleur qui vat s'occuper des APIs. Ajouter, Nouvel élément..., "Classe de contrôleur d'API - Vide", que je vais nommé MeetupsApiControlleur .
Les données accéssibles sur "https://localhost:44392/api/MeetupsApiControlleur". Ca y est, maintenant une application qui a besoin des données, eh bien on lui a fournit une API qui permet de récupérer la liste des meetups.
L'étape suivante est de pouvoir rajouter des meetups. Sur la page Meetups, il y a un lien pour créer un nouveau meetups. Quand on clique dessus, ça vat vers Meetups/Create qui est une action qui n'existe pas encore. Rajouter la méthode Add dans IDataAccess et dans InMemoryDataAccess .
Sauf que en modifiant InMemoryDataAccess, on risque de casser ceux qui fonctionnait bien avant, d'ou l'intérêt de faire du test unitaire. Quand il y aura un autre gugus qui reprendra mon code et qui le cassera, parce qu'il comprendra pas très bien ce que j'ai fait. Quand se sera pété, et qu'il n'y a pas de tests automatisés, eh bien on reviendra vous voir un mois après en vous disant; c'est ta partie, et vous devez retrouver que c'était un gugus qui a fait une modif il y a un mois.
Pour cela créer un nouveau Projet de test: sur la solution faire un click droit, Ajouter, Nouveau projet... Projet de test MSTest (.NET Core). Il existe aussi un type de projet de tests: Xunit, et des frameworks tiers tel que Nunit. On l'appelle du même nom que la solution, en rajoutant "Test" à la fin. Visual Studio vat créer une classe par défaut UnitTest1, que l'on vat renommer ainsi : InMemoryDataAccessTests. Un test unitaire est une simple méthode. Et pour que Visual Studio sache que c'est un test automatisé on ajoute l'attribut TestMethod devant et on met dans une classe qui a un attribut TestClass . Il faut que le projet référence le projet qui contient la référence qui m'intéresse. Click droit sur le projet, Ajouter, Référence de projet.
Il n'y a rien de neuf dans un test unitaire, normalement il ne devrai y avoir que du code qui est utilisé ailleur. Et normalement on devrai même commencer à l'écrire avant d'écrire la fonctionnalité; c'est le test driven developpement. Maintenant rajoutez une méthode de test qui ne devrai pas fonctionner. Ainsi les test rouges sont une sorte de ToDo list.
On vat modifier InMemoryDataAccess ainsi:
Il ne reste plus qu'a modifier le contrôleur, et de créer le formulaire qui vat s'appeller Create. Donc dans le dossier Meetups on fait Ajouter Vue, Vue Razor, Modèle Create, Classe de modèle: Meetup .
Visual Studio génère un formulaire html, avec des tagHelpers, qui est l'une des nouveautés d'Asp.Net Core qu'on avait pas en MVC avant. C'est à dire qu'on peut définier ces propres attributs html (comme sur Angular), qui sont interprétés côté server. ex:
La création ne fonctionne pas car a chaque fois il arrive sur le controlleur, et crée un nouveau IDataAccess par injection de dépendances à chaque fois. Et cela vat se résoudre dans l'injection des dépendances; AddTransient c'est quelque chose qui est instancié à chaque fois qu'on le demande. Donc on vat le remplacer par AddSingleton, en disant qu'il sera fait une seule fois pour toute l'application. Tanq que l'application survivra, il restera là. Mais attention, ça ne vat pas rester éternellement, une application Asp.Net c'est voué à planter régulièrement, à s'arrêter. Si c'est dans un compteur, ça s'arrête, ça redemarre Si vous recevez 10000 requettes par seconde, il y a un moment ou ça vat planter souvant, mais c'est tout à fait naturel dans une application Web. Donc si vous avez besoin de quelque chose d'éternel, mettez le en session, en base de donnée.
Maintenant on peut faire Create: MeetupNo11, 20/9/2017 15:00, 20/9/2017 16:00
En production il vaut mieux utiliser IIS, Kestrel si on est pas sous windows. Pour tout ce qui est la gestion des certificats SSL, du cache, kestrel vat pas le faire de base, donc soit on le fait en .NetCore, soit on met un reverse proxy devant. Si on est pas sous windows, le reverse proxy ça peut être un autre comme nginx par exemple.
réf: ASP.NET CORE Pourquoi ? Comment ? - MUG Montpellier #2
https://www.youtube.com/watch?v=z9Y8kENTMlc
Entity Framework est un outil permettant de créer une couche d'accès aux données (DAL pour Data Access Layer) liées à une base de données relationnelle. Il propose la création d'un schéma conceptuel composé d'entités qui permettent la manipulation d'une source de données, sans écrire une seule ligne de SQL, grâce à LinQ To Entities. Comparé à d'autres solutions de mapping objet-relationnel (ORM), Entity Framework assure l'indépendance du schéma conceptuel (entités ou objets) du schéma logique de la base de données, c'est-à-dire des tables. Ainsi, le code produit et le modèle conceptuel ne sont pas couplés à une base de données spécifique.
Sur SQL Server il utilise OFFSET FETCH, disponible à partir de SQL Server 2012
Dans Visual Studio faire New Project, "ASP.NET Core Web Application (.NETCore)". Puis "Application web (Model-View-Controller)" ou "dotnet new mvc". Et on vat l'appelé "MonCatalogueProduit". On vat d'abord créer les entités Categorie et Produit dans un dossier Service
CategorieID est considéré comme une clé primaire selon la convention de nommage. Le mot clé virtual, signifie le mode lazy dans EntityFramework, c'est à dire qu'il ne charge cette donnée que si on la demande avec le mot clé include. Et On crée une propriété de navigation en mettant un champ de type entité (Categorie).
Maintenant, on rajoute les dépendances à entityFramework dans "project.json"
Ou à partir de .Net Core 3, dans MonCatalogueProduit.csproj en faisant un click droit sur le nom du projet, puis Modifier le fichier projet
Ensuite on va créer le contexte de persistance d'entityFramework. C'est à dire qu'on vat créer la classe CatalogueDbContext dans le dossier Service. Elle vat hériter d'une classe qui est hérité d'entityFramework qui s'appelle DbContext. Et dans cette classe on vat déclarer les collections de DbSet dont on a besoin.
Après pour la persistance on a besoin de connaitre la base de donnée, la chaîne de connexion, il existe plusieurs manière de configurer, dans Startup.cs ou tout simplement de redefinir une fonction ici,
C'est une méthode qui est appelé juste après l'instanciation de DbContext
Maintenant on vat créer un projet pour tester de type "Console Application (.Net Core)". Puis dans les références on vat ajouter une référence vers le projet . Dans le Main, on vat mettre:
using(ob) {} permet d'utiliser un objet uniquement dans le block. Il fournit une syntaxe pratique qui garantit l’utilisation correcte d’objets IDisposable ou IAsyncDisposable.
Autre exemple avec Entity Framework Core 5.0:
Définir le projet console comme projet de demarrage, puis l'exécuter. Aller dans Affichage, explorateur de serveur, Connexions de données, nouveau, et connecter la base, pour voir les modifications. Au niveau des entitées, ça marche bien, même sans utiliser d'annotations. Après on peut utiliser les annotations. Elles sont à importer depuis "System.ComponentModel.DataAnnotations.Schema":
Pour utiliser la liste des produits, on vat créer un nouveau controlleur MVC, "ProduitController", dans le dossier Controllers, en cherchant la "classe de contoleur - vide" (MVC). Et dans ce controlleur on vat utiliser DbContext .
On pourrai l'instancier, mais on vat utiliser l'injection de dépendances. Donc
dans Statup on ajoute services.AddDbContext
@model IEnumerable
Bien enlever les autres éléments autogénérés: @page et @{}
Il y a 3 manières de faire pour que la vue connaisse le type du model.
Remarque: Avec .Net Core 3, il faut migrer les nom des classes Bootstrap v3.3.7
vers les classes de Bootstrap v4.3.1 . Par exemple la classe panel devient card,
qui intégre maintenant les flexbox. Voir le guide à cette url:
https://getbootstrap.com/docs/4.1/migration/
Maintenant quand on navigue vers "https://localhost:44383/Produit/Index" on doit voir la liste des produits. Si on veux créer un espace, on crée une classe css dans le fichier wwwroot\css\style.css ou wwwroot\css\site.css
.spacer { margin-top:40px; }
On améliore la page en la rendant responsive, avec bootstrap. Bootstrap divise l'écran en 12 colonnes. md median (écran d'ordinateur), xs extra small (écran d'un smartphone)
@model IEnumerable Pour changer la page par défaut on change la route par défaut dans Startup.cs,
et dans _layout.cshtml on change la barre de menus.
Ensuite on vat créer la pagination: Avec Linq il est possible de rajouter Maintenant il faut créer des liens. Donc pour afficher les différentes pages, au
niveau du controleur, je vais stocker les différents modèles. Puis je crée la
navigation à l'aide des classes bootsrap nav nav-pills et active . Maintenant on veut afficher la catégorie. Donc comme on est en LazyLoading, il
faut au préalable demander la donnée avec Include. Donc la requette deviens: Ensuite on vat créer un lien pour la saisie des produits. Pour créer un produit
on a besoin d'une liste de catégories. Donc on vat la récupéré. Pour afficher le
formulaire on aura besoin de lui transmettre le model, ici un produit. Les html helpers sont fait pour écrire du code html de manière plus simple et
plus élégante. Avec les html helpers on aurai écrit: @html.LabelFor(m => m.DPrix, new { @class = "control-label" })
@html.TextBoxFor(m => m.DPrix, new { @class = "form-control" })
@html.ValidationMessageFor(p => p.Prix, "", new { @class = "text-danger" }) La validation du modèle se fait par les annotations sur l'entitée avec :
[Required]
[MinLength(4),MaxLength(30)]
[Range(10,500000)]
[StringLength(3, ErrorMessage = "Name connot exceed 3 characters")]
[RegularExpression(@"^\d{5}(?:[-\s]\d{4})?$",
ErrorMessage = "Enter a valid zipcode in 55555 or 55555-5555 format")] Maintenant on vat rajouter la recherche Ici quand on clique sur un lien de navigation, il affiche à nouveaux tout. Car
quand on clique sur le lien on ne voit pas le mot clé. Donc dans le controleur
on met la clé dans le model avec ViewBag.motCle = motCle; puis on change le lien
et le champ de saisie du mot clé. Pour finir on corrige le pied de page dans _Layout.cshtml réf: bearer Token
réf: entityframework model-bdd
réf: learnentityframeworkcore
réf: Part 1 Asp Dot Net Core MVC avec Entity Framework
réf: proteger ses API
Si une table a une clé primaire, elle sera mappé par entityframwork directement.
Si une table a une ou plusieurs clés étrangères, et pas de clé primaire, elle
sera mappé en tanq que propriété de navigation, depuis les tables principales. Pour forcer la mise à jour d'une propriété de navigation: il faut juste ajoutter EntityFrameworkExtended réf: Performing Bulk Updates in Entity Framework 6.1+ Part 1
En cas d'erreur, il est utile d'annuler tous les changements en cours afin de
pouvoir par exemple alimenter une table de log, voici la procédure à suivre : réf: DbContext discard changes without disposing
Click droit sur le projet dans l'explorateur de solution, Publier. Creer un .bat
Reprendre le meme port que lorsqu'on lance l'application en débuguage. cd C:\Program Files\IIS Express
iisexpress /path:C:\Dev\Build\Local\patient /port:50339 Il peut être utile de créer un nouveau ASP.NET Core projet 3.0 pour : 1) Si votre solution repose sur global.json, mettre à jour la version dedans "sdk": {
"version": "3.0.100"
} 2) Mettre à jour le fichier projet. ASP.NET Core 3,0 et versions ultérieures
s’exécutent uniquement sur .NET Core. En mettant "netcoreapp3.0" 3) Supprimer les références de package obsolètes Un grand nombre de packages NuGet ne sont pas générés pour ASP.NET Core 3,0. Ces
références de package doivent être supprimées de votre fichier projet. La liste
complète des packages qui ne sont plus produits, sont disponibles sur le site de
Microsoft (Microsoft.AspNetCore, Microsoft.Net.Http.Headers). Les fonctionnalités de ASP. NET Core qui étaient disponibles via l’un de ces
packages sont disponibles dans le cadre de l'infrastructure partagée
Microsoft.AspNetCore.App. L'infrastructure partagée est l’ensemble d’assemblys
(fichiers .dll ) qui sont installés sur l’ordinateur et comprend un composant
d’exécution et un pack de ciblage. Les projets qui ciblent le Microsoft.NET.Sdk.
Web Kit de développement logiciel (SDK) référencent implicitement le Microsoft.
AspNetCore.App Framework. Aucune référence supplémentaire n’est requise pour ces
projets. Ex : Le fichier projet mis à jour pour ASP.NET Core 3,0 : Les projets qui ciblent Microsoft.NET.Sdk ou le Microsoft.NET.Sdk.Razor Kit de
développement logiciel (SDK), doivent ajouter un explicite FrameworkReference à
Microsoft.AspNetCore.App : 4) Examiner les modifications avec rupture Ajouter des références de package pour les assemblys supprimés
ASP.NET Core 3.0 supprime certains assemblys qui faisaient auparavant partie de
la Microsoft.AspNetCore.App Référence du package. Pour visualiser les assemblys
qui ont été supprimés, comparez les 2 dossiers d’infrastructure partagés.
C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\2.2.7 et \3.0.0, avec un
outil tel que Folder Compare Beyond Compare. Pour continuer à utiliser les
fonctionnalités fournies par les assemblys supprimés, référencez les versions
3.0 des packages correspondants 5) Modifications au démarrage Startup.cs services.AddMvc().Set... remplacé par services.AddRazorPages();
IHostingEnvironment remplacé par pour IWebHostEnvironment
app.UseRouting(); a été ajouté
app.UseAuthorization(); a été ajouté
app.UseEndpoints( a été ajouté Migrer Startup.Configurer réf: Migrer de ASP.NET Core 2.2 à 3.0
BeginInvoke :
Exécute le délégué spécifié de manière asynchrone avec les arguments spécifiés,
sur le thread sur lequel le handle sous-jacent du contrôle a été créé. Le BackgroundWorker se trouve dans le paneaud d'outils, Components. Glisser le
composant sur la forme. Il possède 3 événements: Orchard est un CMS (Système de Gestion de Contenu) qui repose sur la plateforme
ASP.NET MVC. Ce CMS est totalement extensible et customisable car il est fondé
sur une architecture moderne. Cet outil est formé d’une base, le cœur du CMS,
auquel nous allons pouvoir ajouter différents « blocs », appelés modules. Ces
derniers sont aussi modifiables, ce qui donne une possibilité infinie de
customisations. Orchard est soutenu par une communauté de développeurs qui
participent à l’évolution du CMS, en créant notamment des modules, des thèmes,
en participant directement à la correction de bugs, voir même à la rédaction de
documentation. Ce CMS représente une solution adéquate pour la création d’un
blog ou d’un site vitrine pour une clientèle qui souhaite avoir la main sur le
contenu de leur site. Il représente aussi une alternative au CMS comme Drupal,
Wordpress, Joomla et s’adresse directement aux développeurs orientés sur les
technologies Microsoft. Pour installer Orchard, il faut Microsoft WebMatrix et Visual Studio(facultatif)
WebMatrix est un outil dédié au développement Web proposé par Microsoft. C’est
un outil facile à prendre en main, qui permet, en quelques clics, de déployer
des sites Web utilisant divers langages de programmation. L ancez WebMatrix puis
sur la page d’accueil, « New » puis dans le menu choisissez « App Gallery ». Dans la galerie, choisissez Orchard puis cliquez sur « Next ». Donnez un nom au site puis cliquez sur « Next », et enfin cliquez sur « I accept
» pour lancer le téléchargement puis l’installation d’Orchard. La première fois
qu’Orchard se lance, une page va s’afficher dans le navigateur. C’est ici que
l’on configure son site. L’installation et la configuration du site sous Orchard sont terminées. De base,
c’est le thème « TheThemeMachine » qui est installé. C’est un thème de base que
l’on peut modifier pour intégrer le design des maquettes. Pour lancer la
solution, il vous suffis d'appuyez sur le bouton « Run » dans WebMatrix. En se rendant sur l’url « /admin », on accède à l’espace d’administration. Les
identifiants créés précédemment permettent de se connecter à cet espace. L’onglet « Content »
Regroupe l’ensemble des contenus du site. C’est ici que l’on va modifier des
pages, articles, contenus spécifiques existants. L’onglet « Content Définition »
Regroupe une liste de tous les types de contenus existants. C’est ici que l’on
crée un type de contenu spécifique. L’onglet « Queries »
Permet de gérer les types de contenu précédemment créé. On peut filtrer les
différents contenus. Par exemple, on crée trois types de contenus différents : A
B et C. Une « Query » permet de récupérer uniquement le type de contenu A. Le
contenu que renvoie la « Query » peut être trié. L’onglet « Taxonomy »
Permet de créer des groupes de mots que l’on pourra utiliser comme catégories.
Chaque terme d’une taxonomie peut être associé à un type de contenu. L’onglet « Widgets »
Regroupe toutes les zones existantes d’une page. Dans une zone, on peut ajouter
des widgets (HTML, Menu, Projection, Blog, Container…). Pour cibler une page
spécifique ou au contraire pour cibler tout le site, il existe des « Layer ». La
« Default Layer » permet de cibler toutes les pages du site. Par conséquent,
lorsqu’on ajoute un widget HTML dans une zone, ce widget sera présent sur toutes
les pages du site. On peut créer des « Layers » et leurs appliquer des règles
pour cibler ou non certaines pages. Par exemple, imaginons que sur un site X,
nous avons une page de contact. Pour enrichir cette page de contact, nous
souhaitons rajouter un widget html dans la zone nommée « Content ». Pour cibler
cette page de contact uniquement, nous devons créer une « layer » associée à une règle sur l’url « /contact ». L’onglet « Media »
Regroupe, comme son nom l’indique, tous les médias du site (image, vidéo,
musique…). Nous avons la possibilité de créer des dossiers pour organiser les
médias. L’onglet « Navigation »
Permet de créer des menus. Dans un menu, nous pouvons ajouter des liens basiques
« Custom Link », du HTML « Html menu Item », de faire appel à une « Query » pour
afficher du contenu spécifique « Query Link », de créer un menu à partir des
Taxonomies que nous avons créé. L’onglet « Tags »
Permet de créer des étiquettes, et de marquer du contenu avec ces étiquettes. La
liste des éléments marqués d’une étiquette est ensuite disponible via l’url
« /Tags/Nom-de-l’étiquette ». L’onglet « Modules »
Va afficher une liste de plugins appelés « Modules » qui sont comparables à des
blocs que l’on vient ajouter au CMS Orchard. Il existe des centaines de modules
qui permettent d’étendre. Il est aussi possible de créer un module entièrement. L’onglet « Themes »
Liste les thèmes installés ainsi qu’une galerie de thèmes existants prêts à être
installé. L’onglet « Users »
Regroupe les différents utilisateurs du site (Admin, Editor, Moderator, Author,
Contributor). Nous pouvons aussi modifier les droits de chaque utilisateur. L’onglet « Settings »
Regroupe les différents paramètres du site classés selon des catégories. Par
exemple, nous pouvons y retrouver des paramétrages concernant la langue du site. SHAPE
Le CMS Orchard est basé sur des modèles d’objets dynamiques appelés « Shapes ».
Ces modèles dynamiques ont pour but de remplacer les modèles standards d’ASP.NET
MVC. L’utilisation d’objets dynamiques nous permet de travailler avec des
structures qui ne sont pas liées à un type statique, étant donné que les objets
ne sont plus définis à la compilation à l’éxécution. A chaque « shape » on
associe un template prédéfinis que l’on pourra surcharger ensuite afin de
modifier le rendu côté client. MODEL
Le modèle représente la composition d’une « shape ». On y retrouve des attributs
« childs », « contentItem », « content », « meta », « classes » etc. Une « shape
» peut être un parent d’une autre « shape », il existe donc une hiérarchie que
l’on peut parcourir pour obtenir certaines informations. Par exemple, pour
écupérer des informations concernant la publication d’un élément, il faut
parcourir le modèle de la manière suivante : « Model.ContentItem.CommonPart »
afin de retrouver des informations comme la date de publication. PLACEMENT
Il n’est pas nécessaire de surcharger les templates pour obtenir le rendu que
l’on souhaite. Il existe un fichier « Placement.info » qui permet d’afficher et
de placer du contenu dans une page sans toucher au template de l’élément. Les
« Best Practices » recommandent l’utilisation du fichier « Placement.info » afin
d'éviter de créer des templates de type « Content », mais plutôt des templates
pour des parties bien spécifiques, et puis ensuite de les arranger grâce au
fichier « Placement.info ». Nous pouvons modifier l’ordre d’affichage des
éléments. Il existe des règles syntaxiques pour bien faire fonctionner ce
fichier. TEMPLATE
Aperçu du template utilisé. Le template peut être modifié en créant des «
Alternates » (cf Shape Tracing Module). HTML
Aperçu du rendu HTML de l’élément sélectionné. Vous savez maintenant tout ce qu'il y a à savoir pour bien débuter avec Orchard!
Pour approfondir certaines parties ou si un problème se pose, la documentation
est disponible sur le site officiel du CMS Orchard réf: Orchard CMS
réf: site officiel du CMS Orchard
réf: déployer des applications .Net sur Google Cloud
réf: azure
réf:
...
public IActionResult Index(int page=0, int size=5) {
int position = page * size;
IEnumerable<Produit> produits =
dbContext.Produits.skip(position).Take(size).ToList();
public IActionResult Index(int page=0, int size=5) {
...
ViewBag.currentPage = page;
int totalPages;
int nbreProduit = dbContext.Produits.ToList().Count;
if(nbreProduit % size ==0 ) {
totalPages = nbreProduit/size;
}else{
totalPages = 1+ nbreProduit / size ;
}
ViewBag.totalPages = totalPages;
IEnumerable<Produit> produits = <tr>
dbContext <td>@p.ProduitID</td>
.Produits <td>@p.Prix</td>
.skip(position) <td>@p.Categorie.NomCategorie</td>
.Take(size) </tr>
.Include(p => p.Categorie)
.ToList();
public IActionResult FormProduit()
{
Produit p = new Produit();
IEnumerable<Categorie> cats = dbContext.Categories.ToList();
ViewBag.categories = cats;
return View("FormProduit",p);
}
FormProduit.cshtml
@model MonCatalogueProduit.Service.Produit
@{
ViewData["titre"] = "Saisie d'un produit";
}
<p></p>
<div class="container col-md-8 col-md-offset-2">
<div class="panel panel-primary">
<div class="panel-heading">Saisie d'un produit</div>
<div class="panel-body">
<form method="post" asp-action="SaveProduit">
<div class="form-group">
<label class="control-label">Prix</label>
<input type="text" name="Designation" value="@Model.Prix" class="form-control" />
@Html.ValidationMessageFor(p => p.Prix, "", new { @class = "text-danger" })
</div>
<div class="form-group">
<label class="control-label">Categorie</label>
<select name="CategorieID">
@{
foreach (var c in ViewBag.categories)
{
<option value="@c.CategorieID">@c.NomCategorie</option>
}
}
</select>
</div>
<div>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
</div>
</div>
</div>
ProduitController.cs
[HttpPost]
public IActionResult SaveProduit(Produit p)
{
IEnumerable<Categorie> cats = dbContext.Categories.ToList();
ViewBag.categories = cats;
if (ModelState.IsValid)
{
dbContext.Produits.Add(p);
dbContext.SaveChanges();
return RedirectToAction("Index");
}
// si le formulaire est invalide retourne le meme produit qui a été saisie
// dans le formulaire. Il faut aussi créer la liste des catégories.
return View("FormProduit", p);
}
Produits.cshtml
<div class="container">
<form method="get" asp-action="Index">
<label>Mot clé:</label>
<input type="text" name="motCle" />
<button type="submit" class="btn btn-primary">Chercher</button>
</form>
</div>
ProduitController.cs
public IActionResult Index(int page=0,int size=5,string motCle="")
{
int position = page * size;
IEnumerable<Produit> produits = dbContext.Produits
.Where(p=>p.Designation.Contains(motCle))
.Skip(position) // LINQ query syntax
.Take(size)
.Include(p=>p.Categorie)
.ToList();
ViewBag.currentPage = page;
int totalPages;
int nbreProduit = dbContext.Produits
.Where(p => p.Designation.Contains(motCle)).ToList().Count;
...
<input type="text" name="motCle" value="@ViewBag.motCle"/>
...
<li class="@className">
<a asp-action="Index" asp-route-page="@i"
asp-route-motCle="@ViewBag.motCle">@i</a>
</li>
<footer class="navbar-fixed-bottom">
<hr />
<p>© 2018 - GestionProduits</p>
</footer>
https://blogs.infinitesquare.com/posts/web/mise-en-place-d-une-authentification-par-bearer-token-dans-une-application-aspnet-core
https://kite37.wordpress.com/tag/entity-framework-model-bdd-edmx-entite-association-sql/
https://www.learnentityframeworkcore.com/relationships/managing-one-to-many-relationships
https://www.youtube.com/watch?v=i-vVophSz3Y
https://www.youtube.com/watch?v=tDGr2qm_NlA
https://www.youtube.com/watch?v=4johHIG-BSA4.5. EntityFramework
Mappage des tables
Proprietes de navigation issues d'une table de transposition 1-n
public Structure Update(Structure structure)
{
this.contextProvider.Context.Entry(structure).State = EntityState.Modified;
this.contextProvider.Context.SaveChanges();
return structure;
}
public Structure Update()
{
this.contextProvider.Context.Entry(structure).State = EntityState.Modified;
this.contextProvider.Context.SaveChanges();
return structure;
}
/// <summary>
/// Permet de gérer l'affichage des actes ou des catégories
/// </summary>
/// <param name="structure"></param>
/// <param name="actCategory"></param>
/// <param name="isActive">-1 : toggle, 0 : Exclusion, 1 : Activation </param>
/// <returns></returns>
private bool ManageCategory(Structure structure, ActCategory actCategory, int isActive = -1)
{
structure = structureRepository.GetById(structure.idStructure);
if (structure == null)
{
return false;
}
bool active = false;
if (isActive == -1) //Action auto sur parents
{
if (structure.ActCategory.Contains(actCategory))
{
structure.ActCategory.Remove(actCategory);
active = true;
}
else
{
structure.ActCategory.Add(actCategory);
active = false;
}
}
switch (isActive) //Action spécifique sur enfants
{
case 1:
if (structure.ActCategory.Contains(actCategory))
{
structure.ActCategory.Remove(actCategory);
}
break;
case 0:
if (!structure.ActCategory.Contains(actCategory))
{
structure.ActCategory.Add(actCategory);
}
break;
default:
break;
}
structureRepository.Update();
structureRepository.Update(structure);
return active;
}
BulkDelete
public static void MyBulkDelete(VISIOCLOUD_TEMP_TEST Ctx, IQueryable query)
{
string selectSql = query.ToString();
string deleteSql = "DELETE [Extent1] "
+ selectSql.Substring(selectSql.IndexOf("FROM"));
var internalQuery = query.GetType().GetFields(BindingFlags.NonPublic
| BindingFlags.Instance)
.Where(field => field.Name == "_internalQuery")
.Select(field => field.GetValue(query)).First();
var objectQuery = internalQuery.GetType()
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(field => field.Name == "_objectQuery")
.Select(field => field.GetValue(internalQuery)).First() as ObjectQuery;
var parameters = objectQuery.Parameters
.Select(p => new SqlParameter(p.Name, p.Value)).ToArray();
Ctx.Database.ExecuteSqlCommand(deleteSql, parameters);
}
List<int> idAbsenceToDelete = toDelete.Select(x => x.idAbsence).ToList();
MyBulkDelete(_ctx,
_ctx.DoctolibAbsence.Where(x => idAbsenceToDelete.Contains(x.idAbsence)));
MyBulkDelete(_ctx,
_ctx.Absence.Where(x => idAbsenceToDelete.Contains(x.idAbsence)));
BulkInsert
List<Absence> toAdd = new List<Absence>();
Absence absence = new Absence { } ...
toAdd.Add(absence);
Ctx.AddRange(toAdd);
var formatUpdQry = "('idClient',{0},'{1}'),";
string queryString = "INSERT INTO options (idClient, font,size) VALUES ";
foreach(...)
queryString += String.Format(formatUpdQry, 'Arial', 12);
queryString = queryString.Substring(0, queryString.Length - 1)
.Replace("'idClient'", 123);
Ctx.Database.ExecuteSqlCommand(queryString);
BulkUpdate
using EntityFramework.Extensions;
var invoivesIds = lotOfInvoice.FORMAT.Select(e => e.ActInvoice.Id).ToList();
Ctx.ActInvoice.Where(item => invoivesIds.Contains(item.Id))
.Update(x => new ActInvoice() {
TeletransmissionStatus = 3,
DateLastModification = dtExec
});
https://www.seguetech.com/performing-bulk-updatesentity-framework-6-1/Annuler tous les changements en cours
public void RejectChanges()
{
RejectScalarChanges();
RejectNavigationChanges();
}
private void RejectScalarChanges()
{
var changedEntries = _dbContext.ChangeTracker.Entries()
.Where(e => e.State != EntityState.Unchanged);
foreach (var entry in changedEntries)
{
switch (entry.State)
{
case EntityState.Added:
entry.State = EntityState.Detached;
break;
case EntityState.Modified:
entry.State = EntityState.Unchanged;
break;
// Where a Key Entry has been deleted, reloading from the source is
// required to ensure that the entity's relationships are restored
// (undeleted).
case EntityState.Deleted:
entry.Reload();
break;
}
}
}
private void RejectNavigationChanges()
{
ObjectContext objectContext = ((IObjectContextAdapter)_dbContext).ObjectContext;
var addedRelationships = objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added)
.Where(e => e.IsRelationship);
var deletedRelationships = objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted)
.Where(e => e.IsRelationship && !RelationshipContainsKeyEntry(e));
foreach (var relationship in addedRelationships)
relationship.Delete();
foreach (var relationship in deletedRelationships)
relationship.ChangeState(EntityState.Unchanged);
bool RelationshipContainsKeyEntry(ObjectStateEntry stateEntry)
{
var keys = new[] { stateEntry.OriginalValues[0], stateEntry.OriginalValues[1] };
return keys.Any(key => objectContext.ObjectStateManager.GetObjectStateEntry(key).Entity == null);
}
}
https://stackoverflow.com/questions/16437083/dbcontext-discard-changes-without-disposing
réf: Discard Changes Without Disposing DbContext/ObjectContext in EF6
https://www.c-sharpcorner.com/UploadFile/ff2f08/discard-changes-without-disposing-dbcontextobjectcontext-in/4.6. Deployer une application ASP.NET
4.7. Migrer de ASP.NET Core 2.2 à 3.0
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App"/>
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
...
</Project>
https://docs.microsoft.com/fr-fr/aspnet/core/migration/22-to-30?view=aspnetcore-3.1&tabs=visual-studio
https://docs.microsoft.com/fr-fr/aspnet/core/migration/22-to-30?view=aspnetcore-5.0&tabs=visual-studio
réf: Mappage entre propriétés project.json et csproj
https://docs.microsoft.com/fr-fr/dotnet/core/tools/project-json-to-csproj
réf: Librairie coté client LibMan
https://www.c-sharpcorner.com/article/client-side-package-management-with-library-manager-in-visual-studio-2017libman/
réf encryptage de mot de passe
https://stackoverflow.com/questions/11412882/hash-password-in-c-bcrypt-pbkdf2CHAPITRE 5 - Fiches, Composants et ressources.
5.1. Communication entre les controles
Job.cs
public class Job
{
public int ID { get; set; }
public string Title { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
JobChangedEventArgs.cs
public class JobChangedEventArgs : EventArgs
{
public Job Job { get; set; }
}
Mediator.cs
public sealed class Mediator
{
// static members
private static readonly Mediator _Instance = new Mediator();
private Mediator() { }
public static Mediator GetInstance()
{
return _Instance;
}
// Instance fonctionality
public event EventHandler<JobChangedEventArgs> JobChanged;
public void OnJobChanged(object sender, Job job)
{
var jobChangeDelegate = JobChanged as EventHandler<JobChangedEventArgs>;
if (jobChangeDelegate != null)
{
jobChangeDelegate(sender, new JobChangedEventArgs { Job = job });
}
}
}
Jobs.xaml.cs
private void JobsComboBox_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
Mediator.GetInstance().OnJobChanged(this, (Job)JobsComboBox.SelectedItem);
}
JobDetails.xaml.cs
public JobDetails()
{
InitializeComponent();
Mediator.GetInstance().JobChanged += (s, e) =>
{
this.DataContext = e.Job;
};
}
EmployeesOnJob.xaml.cs
public partial class EmployeesOnJob : UserControl
{
List<Employee> _Employees = new List<Employee> {
new Employee { ID = 1, Name = "John Doe", Jobs = new List<Job>
{
new Job { ID = 1, Title = "Area 1 Maintenance" },
new Job { ID = 2, Title = "Edge Park" },
new Job { ID = 3, Title = "Paint Benches" },
new Job { ID = 4, Title = "Build New Wall" }
}
},
new Employee { ID = 2, Name = "Jane Doe", Jobs = new List<Job>
{
new Job { ID = 3, Title = "Paint Benches" },
new Job { ID = 4, Title = "Build New Wall" }
}
},
new Employee { ID = 3, Name = "Michelle Davis", Jobs = new List<Job>
{
new Job { ID = 1, Title = "Area 1 Maintenance" },
new Job { ID = 3, Title = "Paint Benches" }
}
},
};
public EmployeesOnJob()
{
InitializeComponent();
Mediator.GetInstance().JobChanged += (s, e) =>
{
BindData(e.Job);
};
}
private void BindData(Job job)
{
this.DataContext = job;
var emps = _Employees.Where(e => e.Jobs.Any(j => j.ID == job.ID));
EmployeesListView.ItemsSource = emps;
}
}
5.2. Traitement asynchrone sur les controles
delegate void StartProgressDelegate(int val);
delegete void ShowProgressDelegate(int val);
private void StartButton_Click(object Sender, System.EventArgs e)
{
StartProgressDelegate progDel = new StartProgressDelegate(StartProcess);
progDel.BeginInvoke(100, null, null);
MessageShow("Done with operation!!");
}
private void StartProcess(int max)
{
ShowProgress(0);
for (int i=0; i <= max; i++)
{
Tread.Sleep(10);
ShowProgress(i);
}
}
private void ShowProgress(int i)
{
// This is hit if background thread calls ShowProgress()
if (lblOutput.InvokeRequired) {
var del = new ShowProgressDelegate(ShowProgress);
this.BeginInvoke(del, new object[] { i });
}
else {
lblOutput.Text = i.ToString();
pbStatus.Value = i;
}
}
5.3. Utilisation des evenement Background
private void StartButton_Click(object sender, EventArgs e)
{
StartButton.Enabled = false;
CancelButton.Enabled = true;
OutputLabel.Text = "";
MyBackgroundWorker.RunWorkerAsync();
}
private long Calculate(BackgroundWorker instance, DoWorkEventArgs e)
{
for (int i = 0; i < 100; i++)
{
if (instance.CancellationPending) {
e.Cancel = true;
break;
}
else {
System.Threading.Thread.Sleep(100);
instance.ReportProgress(i);
}
return 0L;
}
}
private void CancelButton_Click(object sender, EventArgs e)
{
MyBackgroundWorker.CancelAsync();
CancelButton.Enabled = false;
}
private void MyBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
//Not on a UIThread
e.result = Calculate(sender as BackgroundWorker, e);
}
private void MyBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void MyBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
StartButton.Enabled = true;
progressBar1.Value = 0;
if (!e.Cancelled) {
OutputLabel.Text = "BackgroundWorker Completed!";
}
else {
OutputLabel.Text = "Concelled!";
}
}
5.4. Utilisation des threads
delegete void StartProgressHandler();
private void StartButton_Click(object sender, EventArgs e)
{
var t = new Thread(new ThreadStart(StartProcess));
t.Start();
}
private void StartProcess()
{
if (pbStatus.InvokeRequired)
{
var sph = new StartProgressHandler(StartProcess);
this.Invoke(sph);
}
else {
this.Refresh();
this.pbStatus.Maximum = max;
for (int i=0; i <= max; i++)
{
Tread.Sleep(10);
lblOutput.Text = i.ToString();
pbStatus.Value = i;
}
}
}
CHAPITRE 6 - Gestionnaires de contenus CMS
6.1. Orchard CMS
Installation
Espace d'administration
Compréhension indispensable
https://www.supinfo.com/articles/single/1120-orchard-cms#idm44858314143056
https://docs.orchardproject.net/en/latest/Documentation/Basic-Orchard-Concepts/
réf: site officiel du CMS Orchard comment ça marche
https://docs.orchardproject.net/en/latest/Documentation/How-Orchard-works/
https://cloud.google.com/solutions/deploy-dotnet-applications?hl=fr
réf: CMS
https://www.ovh.com/fr/hebergement-web/site/comparatif-cms/
https://docs.microsoft.com/fr-fr/learn/azure/
réf: devOps
https://www.developpez.com/actu/166144/DevOps-avec-Azure-moins-Partie-3-apprendre-a-creer-et-a-deployer-des-ressources-avec-Visual-Studio-et-ARM-Template-par-Hinault-Romaric/
https://www.developpez.com/actu/191112/DevOps-avec-Azure-moins-Partie-6-apprendre-a-mettre-en-place-une-strategie-de-CI-CD-pour-l-infrastructure-et-le-Code-moins-Approche-2-par-Hinault-Romaric/
réf: API .Net
https://docs.microsoft.com/fr-fr/dotnet/api/?view=netcore-3.1
http://index-of.co.uk/Microsoft-Compiled-HTML-Help/
Programming / Coding / Hacking music
https://www.youtube.com/watch?v=5Yvu2htHKL4