0% ont trouvé ce document utile (0 vote)
110 vues127 pages

Dotnet Architecture Blazor For Web Forms Developers

Transféré par

pascal
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
110 vues127 pages

Dotnet Architecture Blazor For Web Forms Developers

Transféré par

pascal
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Parlez-nous de l’expérience de téléchargement de PDF.

Blazor pour les développeurs ASP.NET


Web Forms
Article • 08/02/2023

TÉLÉCHARGEMENT disponible à l’adresse suivante : https://aka.ms/blazor-ebook


EDITION v6.0 - Mise à jour vers .NET 6

Consultez le journal des modifications pour voir les mises à jour du livre et les
contributions de la communauté.

PUBLIÉ PAR

Division Développeurs Microsoft, équipes produit .NET et Visual Studio

Division de Microsoft Corporation

One Microsoft Way

Redmond, Washington 98052-6399

Copyright © 2022 Microsoft Corporation

Tous droits réservés. Aucune partie du contenu de ce document ne peut être reproduite
ou transmise sous quelque forme ou par quelque moyen que ce soit sans l’autorisation
écrite de l’éditeur.

Ce document est fourni « en l’état » et exprime les points de vue et les opinions de son
auteur. Les points de vue, les opinions et les informations exprimés dans cet ouvrage,
notamment l’URL et autres références à des sites web Internet, peuvent faire l’objet de
modifications sans préavis.

Certains exemples sont fournis à titre indicatif uniquement et sont fictifs. Toute
association ou lien est purement involontaire ou fortuit.

Microsoft et les marques commerciales mentionnées dans la page web « Marques » sur
https://www.microsoft.com sont des marques du groupe Microsoft.

Mac et macOS sont des marques commerciales d’Apple Inc.

Toutes les autres marques et tous les autres logos sont la propriété de leurs
propriétaires respectifs.

Auteurs :

Daniel Roth , Responsable de programme principal, Microsoft Corp.

Jeff Fritz , Responsable de programme senior, Microsoft Corp.

Taylor Southwick , Ingénieur logiciel senior, Microsoft Corp.


Scott Addie , Développeur de contenu senior, Microsoft Corp.

Steve « @ardalis » Smith , Architecte et formateur logiciel, NimblePros.com

Introduction
.NET a longtemps pris en charge le développement d’applications web via ASP.NET, un
ensemble complet d’infrastructures et d’outils pour la génération de tout type
d’application web. ASP.NET possède sa propre lignée d’infrastructures et technologies
web, qui trouve ses racines dans la technologie Active Server Pages (ASP) classique. Des
infrastructures comme ASP.NET Web Forms, ASP.NET MVC, Pages Web ASP.NET et, plus
récemment, ASP.NET Core, offrent un moyen productif et puissant de produire des
applications web rendues par le serveur, où le contenu de l’interface utilisateur est
généré de façon dynamique sur le serveur en réponse à des requêtes HTTP. Chaque
infrastructure ASP.NET s’adresse à un public et découle d’une philosophie de création
d’application spécifiques. ASP.NET Web Forms fourni avec la version d’origine de .NET
Framework, a ouvert la voie au développement web à l’aide de nombreux modèles
familiers pour les développeurs d’applications de bureau, comme des contrôles
d’interface utilisateur réutilisables avec une gestion simple des événements. Toutefois,
aucune offre d’ASP.NET ne permet d’exécuter du code dans le navigateur de l’utilisateur.
Cela requiert d’écrire du JavaScript et d’utiliser l’un des nombreux outils et
infrastructures qui ont gagné, puis perdu en popularité au fil des ans, tels que jQuery,
Knockout, Angular, React, etc.

Blazor est une nouvelle infrastructure web qui change les possibilités de création
d’applications web avec .NET. Blazor est une infrastructure d’interface utilisateur web
côté client basée sur C# au lieu de JavaScript. Blazor vous permet d’écrire vos
composants logiques et votre interface utilisateur côté client en C#, de les compiler
dans des assemblys .NET standard, puis de les exécuter directement dans un navigateur
utilisant d’une nouvelle norme web ouverte appelée WebAssembly. Ou bien, Blazor peut
exécuter vos composants d’interface utilisateur .NET sur le serveur, et gérer toutes les
interactions avec l’interface utilisateur de manière fluide sur une connexion en temps
réel avec le navigateur. Associé à .NET s’exécutant sur le serveur, Blazor permet un
développement web de pile complète avec .NET. Bien que Blazor partage de nombreux
points communs avec ASP.NET Web Forms, comme d’avoir un modèle de composant
réutilisable et une manière simple de gérer les événements utilisateur, il s’appuie
également sur les fondements de .NET pour fournir une expérience de développement
web moderne et hautement performante.

Ce livre présente Blazor aux développeurs ASP.NET Web Forms d’une manière familière
et pratique. Il introduit les concepts de Blazor en parallèle avec des concepts analogues
dans ASP.NET Web Forms, tout en expliquant de nouveaux concepts susceptibles d’être
moins familiers. Il couvre un vaste éventail de sujets et préoccupations, dont la création,
le routage, la disposition, la configuration et la sécurité des composants. Et bien que le
contenu de ce livre soit principalement destiné à ouvrir la voie à de nouveaux
développements, il fournit également des instructions et stratégies pour la migration
vers Blazor d’applications ASP.NET Web Forms existantes que vous souhaitez
moderniser.

Public cible du livre


Ce livre est destiné aux développeurs ASP.NET Web Forms en quête d’une introduction
à Blazor qui soit en lien avec leurs connaissances et compétences existantes. Il peut
aider à démarrer rapidement un nouveau projet basé sur Blazor, ou à tracer une feuille
de route pour la modernisation d’une application ASP.NET Web Forms existante.

Utilisation du livre
La première partie de ce livre décrit Blazor et le compare au développement
d’application web avec ASP.NET Web Forms. Le livre couvre ensuite divers aspects de
Blazor, chapitre par chapitre, en associant chaque concept de Blazor à un concept
correspondant dans ASP.NET Web Forms, ou en expliquant de façon approfondie les
concepts entièrement nouveaux. Le livre fait également régulièrement référence à un
échantillon d’application complète implémentée tant dans ASP.NET Web Forms que
dans Blazor, afin de montrer les fonctionnalités de Blazor et de fournir une étude de cas
pour la migration d’ASP.NET Web Forms vers Blazor. Vous trouverez les deux
implémentations de l’échantillon d’application (versions ASP.NET Web Forms et Blazor)
sur GitHub .

Ce que ce livre ne couvre pas


Ce livre est une introduction à Blazor, pas un guide de migration exhaustif. Bien qu’il
inclue des conseils sur la façon d’aborder la migration d’un projet d’ASP.NET Web Forms
vers Blazor, il ne tente nullement de couvrir chaque nuance ou détail de l’opération.
Pour des informations plus générales sur la migration d’ASP.NET vers ASP.NET Core,
consultez les conseils de migration fournis dans la documentation ASP.NET Core.

Ressources supplémentaires
Vous trouverez la page d’accueil et la documentation officielles de Blazor à l’adresse
https://blazor.net .

Envoyez votre feedback


Le livre et les exemples associés étant en constante évolution, vos commentaires sont
les bienvenus. Si vous avez des commentaires sur la façon dont ce livre peut être
amélioré, utilisez la section des commentaires au bas des pages reposant sur GitHub
Issues .

Next
Présentation de Blazor pour les
développeurs ASP.NET Web Forms
Article • 08/06/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor pour les développeurs ASP
NET Web Forms pour Azure, disponible dans la documentation .NET ou au format
PDF à télécharger gratuitement pour le lire hors connexion.

Télécharger le PDF

Le framework ASP.NET Web Forms est un incontournable du développement web .NET


depuis la première publication du .NET Framework en 2002. Alors que le web était
encore à ses tout premiers balbutiements, ASP.NET Web Forms a rendu la création
d’applications web simple et productive en adoptant un grand nombre des schémas qui
étaient utilisés pour le développement de bureau. Dans ASP.NET Web Forms, les pages
web peuvent être rapidement composées à partir de contrôles IU réutilisables. Les
interactions utilisateur sont gérées naturellement comme des événements. Il existe un
riche écosystème de contrôles IU Web Forms fournis par Microsoft et les fournisseurs de
contrôles. Les contrôles allègent les efforts pour se connecter aux sources de données et
pour afficher des visualisations de données riches. Pour l’aspect visuel, le concepteur
Web Forms fournit une interface simple par glisser-déposer pour gérer les contrôles.

Année après année, Microsoft a introduit de nouveaux frameworks web basés sur
ASP.NET pour répondre aux tendances du développement web. Parmi ces frameworks
web, citons ASP.NET MVC, ASP.NET Web Pages et plus récemment ASP.NET Core.
Chaque fois qu’un nouveau framework sortait, certains prédisaient le déclin imminent
d’ASP.NET Web Forms et le critiquaient en affirmant que c’était un framework web
obsolète et démodé. Malgré ces prédictions, de nombreux développeurs web .NET
continuent de voir ASP.NET Web Forms comme un moyen simple, stable et productif de
faire leur travail.

À l’heure où nous rédigeons cet article, près d’un demi-million de développeurs web
utilisent ASP.NET Web Forms chaque mois. Le framework ASP.NET Web Forms est stable
au point que la documentation, les exemples, les livres et les billets de blog écrits il y a
dix ans ont gardé toute leur utilité et leur pertinence. Pour de nombreux développeurs
web .NET, « ASP.NET » reste synonyme de « ASP.NET Web Forms » comme c’était le cas
quand .NET a été conçu pour la première fois. Les arguments sur les pour et les contre
d’ASP.NET Web Forms par rapport aux autres nouveaux frameworks web .NET peuvent
continuer à faire rage. ASP.NET Web Forms reste un framework populaire pour créer des
applications web.

Malgré tout, les innovations dans le développement logiciel ne ralentissent pas. Tous les
développeurs de logiciels doivent rester au courant des nouvelles technologies et
tendances. Deux tendances en particulier méritent notre attention :

1. Le passage à l’open source et au multiplateforme


2. Le passage de la logique d’application au client

Un .NET open source et multiplateforme


Lorsque .NET et ASP.NET Web Forms ont été publiés pour la première fois, l’écosystème
de la plateforme était très différent de ce qu’il est aujourd’hui. Les marchés Desktop et
Server étaient dominés par Windows. D’autres plateformes comme macOS et Linux
luttaient encore pour se faire une place. ASP.NET Web Forms est livré avec le .NET
Framework en tant que composant uniquement Windows, ce qui signifie que les
applications ASP.NET Web Forms ne peuvent s’exécuter que sur des ordinateurs
Windows Server. Actuellement, de nombreux environnements modernes utilisent
différents types de plateformes pour les serveurs et les ordinateurs de développement,
de sorte que la prise en charge multiplateforme est une condition sine qua non pour de
nombreux utilisateurs.

La plupart des frameworks web modernes sont aussi maintenant open source, ce qui
présente un certain nombre d’avantages. Les utilisateurs ne sont pas tenus à un seul
propriétaire de projet pour corriger les bogues et ajouter des fonctionnalités. Les projets
open source offrent une meilleure transparence sur la progression du développement et
les changements à venir. Les projets open source bénéficient des contributions de toute
une communauté et favorisent un écosystème open source de grand soutien. Malgré les
risques liés à l’open source, de nombreux consommateurs et contributeurs ont trouvé
des atténuations appropriées qui leur permettent de profiter des avantages d’un
écosystème open source de manière sûre et raisonnable. Parmi ces atténuations, citons
les contrats de licence de contributeur, les licences conviviales, les analyses de pedigree
et les fondations de soutien.

La communauté .NET a adopté la prise en charge du multiplateforme et l’open source.


.NET Core est une implémentation open source et multiplateforme de .NET qui s’exécute
sur une multitude de plateformes, notamment Windows, macOS et diverses
distributions Linux. Xamarin fournit Mono, version open source de .NET. Mono s’exécute
sur Android, iOS et divers autres facteurs de forme, notamment les montres et les
télévisions intelligentes. En 2020, Microsoft a publié .NET 5 qui a réuni .NET Core et
Mono dans « un seul runtime et framework .NET qui peut être utilisé partout et qui a
des comportements d’exécution et des expériences de développement uniformes ».

Est-ce qu’ASP.NET Web Forms tire parti du passage à l’open source et à la prise en
charge du multiplateforme ? Malheureusement, la réponse est non, ou du moins pas
autant que le reste de la plateforme. L’équipe .NET a clairement indiqué qu’ASP.NET
Web Forms ne sera pas porté sur .NET Core ou .NET 7. Pourquoi ?

Des efforts ont été faits au début de .NET Core pour porter ASP.NET Web Forms. Le
nombre de changements cassants requis a été jugé trop élevé. Il a également été admis
que, même pour Microsoft, le nombre de frameworks web qu’il peut prendre en charge
simultanément est limité. Peut-être qu’une personne de la communauté embrassera la
cause et créera une version open source et multiplateforme d’ASP.NET Web Forms. Le
code source d’ASP.NET Web Forms a été mis à la disposition de tout le monde sous
forme de référence. Mais pour l’instant, il semble qu’ASP.NET Web Forms reste réservé à
Windows et sans modèle de contribution open source. Si la prise en charge du
multiplateforme ou l’open source deviennent importants pour vos scénarios, vous
devrez alors rechercher quelque chose de nouveau.

Cela signifie-t-il qu’ASP.NET Web Forms est mort et ne devrait plus être utilisé ? Bien sûr
que non ! Tant que le .NET Framework est fourni avec Windows, ASP.NET Web Forms
reste un framework pris en charge. Pour de nombreux développeurs Web Forms,
l’absence de prise en charge du multiplateforme et de l’open source n’est pas un
problème. Si vous n’avez pas besoin de la prise en charge du multiplateforme, de l’open
source ou de l’une des autres nouvelles fonctionnalités de .NET Core ou de .NET 7, vous
pouvez très bien continuer à utiliser ASP.NET Web Forms sur Windows. ASP.NET Web
Forms reste et restera un moyen productif d’écrire des applications web pendant encore
de nombreuses années.

Toutefois, une autre tendance est à prendre en considération : le passage au client.

Développement web côté client


Tous les frameworks web basés sur .NET, y compris ASP.NET Web Forms, ont toujours eu
une chose en commun : ils sont rendus via un serveur. Dans les applications web
rendues via un serveur, le navigateur envoie une demande au serveur, qui exécute du
code (code .NET dans les applications ASP.NET) pour produire une réponse. Cette
réponse est renvoyée au navigateur pour qu’il la gère. Dans ce modèle, le navigateur est
utilisé comme moteur de rendu dynamique. Une grande partie du travail consistant à
produire l’interface utilisateur, exécuter la logique métier et gérer l’état se fait sur le
serveur.

Toutefois, les navigateurs sont devenus des plateformes polyvalentes. Ils implémentent
un nombre toujours croissant de normes web ouvertes qui accordent l’accès aux
fonctionnalités de l’ordinateur de l’utilisateur. Pourquoi ne pas tirer parti de la puissance
de calcul, du stockage, de la mémoire et autres ressources de l’appareil client ? Les
interactions avec l’interface utilisateur en particulier peuvent bénéficier d’une expérience
plus riche et plus interactive lorsqu’elles sont gérées au moins partiellement ou
complètement côté client. La logique et les données qui doivent être gérées sur le
serveur peuvent toujours être gérées côté serveur. Les appels d’API web ou même les
protocoles en temps réel, tels que WebSockets, peuvent être utilisés. Les développeurs
web peuvent disposer gratuitement de ces avantages s’ils sont prêts à écrire en
JavaScript. Les frameworks d’interface utilisateur côté client, comme Angular, React et
Vue, simplifient le développement web côté client et ont gagné en popularité. Les
développeurs ASP.NET Web Forms peuvent également tirer parti du client et même
bénéficier d’un support immédiat avec des frameworks JavaScript intégrés comme
ASP.NET AJAX.

Mais le pontage de deux plateformes et écosystèmes différents (.NET et JavaScript) a un


coût. Une maîtrise de deux mondes parallèles avec différents langages, frameworks et
outils est requise. Le code et la logique ne peuvent pas être facilement partagés entre le
client et le serveur, ce qui entraîne des duplications et une surcharge en ingénierie. Il
peut également être difficile de suivre l’écosystème JavaScript, qui a l’habitude d’évoluer
à une vitesse vertigineuse. Les préférences en matière de framework front-end et d’outil
de build changent vite. Le secteur a observé la progression de Grunt à Gulp, puis à
Webpack, et ce n’est pas fini. La même évolution effrénée s’est produite avec les
frameworks front-ends comme jQuery, Knockout, Angular, React et Vue. Mais, au vu du
monopole du navigateur JavaScript, le choix était très mince. Enfin, jusqu’à ce que la
communauté web se réunisse et produise un miracle !

WebAssembly répond à un besoin


En 2015, les principaux fournisseurs de navigateurs ont uni leurs forces dans un groupe
de la communauté W3C pour créer une norme web ouverte appelée WebAssembly.
WebAssembly est un code d’octet pour le web. Si vous pouvez compiler votre code sur
WebAssembly, celui-ci peut ensuite s’exécuter sur n’importe quel navigateur sur
n’importe quelle plateforme à une vitesse quasi native. Les premiers efforts se sont
concentrés sur C/C++. Le résultat était une démonstration spectaculaire de l’exécution
de moteurs graphiques 3D natifs directement dans le navigateur sans plug-ins.
WebAssembly a depuis été standardisé et implémenté par tous les principaux
navigateurs.

Des travaux sur l’exécution de .NET sur WebAssembly ont été annoncés fin 2017 et
publiés en 2020, avec prise en charge dans .NET 5 et ultérieur. La capacité à exécuter du
code .NET directement dans le navigateur permet le développement web full-stack avec
.NET.

Blazor : développement web full-stack avec


.NET
La capacité seule à exécuter du code .NET dans un navigateur ne fournit pas une
expérience de bout en bout pour créer des applications web côté client. C’est là où
Blazor entre en jeu. Blazor est un framework d’interface utilisateur web côté client basé
sur C# au lieu de JavaScript. Blazor peut s’exécuter directement dans le navigateur via
WebAssembly. Aucun plug-in de navigateur n’est requis. Les applications Blazor peuvent
aussi s’exécuter côté serveur sur .NET et gérer toutes les interactions utilisateur sur une
connexion en temps réel avec le navigateur.

Blazor offre une excellente prise en charge des outils dans Visual Studio et Visual Studio
Code. Le framework comprend également un modèle de composant IU complet et
dispose de fonctionnalités intégrées pour :

Formulaires et validation
Injection de dépendances
Routage côté client
Dispositions
Débogage dans le navigateur
Interopérabilité JavaScript

Blazora beaucoup en commun avec ASP.NET Web Forms. Les deux frameworks offrent
des modèles de programmation IU avec état qui sont basés sur des composants et
pilotés par des événements. La principale différence architecturale est qu’ASP.NET Web
Forms s’exécute uniquement sur le serveur. Blazor peut s’exécuter sur le client dans le
navigateur. Mais si vous venez d’ASP.NET Web Forms, beaucoup d’aspects vous
sembleront familiers dans Blazor. Blazor est une solution naturelle pour les
développeurs ASP.NET Web Forms qui cherchent un moyen de tirer parti du
développement côté client et du futur multiplateforme open source de .NET.

Ce livre fournit une présentation de Blazor qui s’adresse spécialement aux développeurs
ASP.NET Web Forms. Chaque concept Blazor est présenté dans le contexte de
fonctionnalités et pratiques ASP.NET Web Forms analogues. À la fin de ce livre, vous
aurez compris :

Comment créer des applications Blazor.


Comment fonctionne Blazor.
Comment Blazor est lié à .NET.
Les stratégies raisonnables pour migrer des applications ASP.NET Web Forms
existantes vers Blazor quand elles sont appropriées.

Commencer à utiliser Blazor


Il est facile de commencer à utiliser Blazor. Accédez à https://blazor.net et suivez les
liens pour installer le SDK .NET et les modèles de projet Blazor appropriés. Vous
trouverez également des instructions pour configurer les outils Blazor dans Visual Studio
ou Visual Studio Code.

Précédent Suivant
Comparaison des architectures ASP.NET
Web Forms et Blazor
Article • 08/06/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor pour les développeurs ASP
NET Web Forms pour Azure, disponible dans la documentation .NET ou au format
PDF à télécharger gratuitement pour le lire hors connexion.

Télécharger le PDF

Même si ASP.NET Web Forms et Blazor comptent de nombreux concepts similaires, leur
fonctionnement présente des différences. Ce chapitre examine les rouages internes et
les architectures d’ASP.NET Web Forms et de Blazor.

ASP.NET Web Forms


Le framework ASP.NET Web Forms est basé sur une architecture orientée page. Chaque
requête HTTP pour un emplacement dans l’application est une page distincte avec
laquelle ASP.NET répond. À mesure que les pages sont demandées, le contenu du
navigateur est remplacé par les résultats de la page demandée.

Les pages présentent les composants suivants :

Balisage HTML
Code C# ou Visual Basic
Classe code-behind contenant des fonctionnalités de logique et de gestion des
événements
Commandes
Les contrôles sont des unités réutilisables de l’interface utilisateur web qui peuvent être
placées et manipulées programmatiquement sur une page. Les pages sont composées
de fichiers qui se terminent par .aspx et qui contiennent des balises, des contrôles et du
code. Les classes code-behind sont dans des fichiers avec le même nom de base et une
extension .aspx.cs ou .aspx.vb, selon le langage de programmation utilisé. Il est
intéressant de noter que le serveur web interprète le contenu des fichiers .aspx et les
compile chaque fois qu’ils changent. Cette recompilation se produit même si le serveur
web est déjà en cours d’exécution.

Les contrôles peuvent être générés avec le balisage et livrés comme contrôles
utilisateur. Un contrôle utilisateur dérive de la classe UserControl et a une structure
similaire à la page. Le balisage des contrôles utilisateur est stocké dans un fichier .ascx.
Une classe code-behind associée réside dans un fichier .ascx.cs ou .ascx.vb. Les contrôles
peuvent aussi être générés intégralement avec le code en héritant de la classe de base
WebControl ou CompositeControl .

Les pages ont également un cycle de vie d’événement complet. Chaque page déclenche
des événements pour l’initialisation, le chargement, le prérendu et le déchargement des
événements qui se produisent lorsque le runtime ASP.NET exécute le code de la page
pour chaque requête.

Les contrôles d’une page sont généralement republiés sur la même page qui présentait
le contrôle et ont avec eux le contenu d’un champ de formulaire masqué appelé
ViewState . Le champ ViewState contient des informations sur l’état des contrôles au
moment où ils ont été rendus et présentés sur la page, ce qui permet au runtime
ASP.NET de comparer et d’identifier les changements du contenu soumis au serveur.

Blazor
Blazor est un framework d’interface utilisateur web côté client similaire à celui des
frameworks front-end JavaScript comme Angular ou React. Blazor gère les interactions
utilisateur et restitue les mises à jour nécessaires de l’interface utilisateur. Blazorn’est pas
basé sur un modèle requête-réponse. Les interactions utilisateur sont gérées comme
des événements qui ne sont pas dans le contexte d’une requête HTTP en particulier.

Les applications Blazor sont constituées d’un ou plusieurs composants racines qui sont
restitués sur une page HTML.
La façon dont l’utilisateur spécifie où les composants doivent s’afficher et la façon dont
les composants sont ensuite reliés pour les interactions utilisateur sont spécifiques au
modèle d’hébergement.

Les composantsBlazor sont des classes .NET qui représentent un élément réutilisable de
l’interface utilisateur. Chaque composant conserve son propre état et spécifie sa propre
logique de rendu, qui peut englober le rendu d’autres composants. Les composants
indiquent des gestionnaires d’événements pour des interactions utilisateur spécifiques
afin de mettre à jour l’état du composant.

Une fois qu’un composant gère un événement, Blazor affiche le composant et suit ce qui
a changé dans la sortie rendue. Les composants ne s’affichent pas directement dans le
modèle DOM (Document Object Model). Ils s’affichent sur une représentation en
mémoire du modèle DOM appelé RenderTree pour permettre à Blazor de suivre les
modifications. Blazor compare la sortie qui vient d’être rendue à la sortie précédente
pour générer un diff de l’interface utilisateur qu’il applique ensuite efficacement au
modèle DOM.
Les composants peuvent également indiquer manuellement qu’ils doivent être rendus si
leur état change en dehors d’un événement d’interface utilisateur normal. Blazor utilise
un SynchronizationContext pour appliquer un seul thread logique d’exécution. Les
méthodes de cycle de vie d’un composant et les rappels d’événements qui sont
déclenchés par Blazor sont exécutés sur ce SynchronizationContext .

Précédent Suivant
Modèles d’hébergement d’applications
Blazor
Article • 08/06/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor pour les développeurs ASP
NET Web Forms pour Azure, disponible dans la documentation .NET ou au format
PDF à télécharger gratuitement pour le lire hors connexion.

Télécharger le PDF

Les applications Blazor peuvent être hébergées de l’une des façons suivantes :

Côté client dans le navigateur sur WebAssembly.


Côté serveur dans une application ASP.NET Core.

Blazor Applications WebAssembly


Blazor Les applications WebAssembly s’exécutent directement dans le navigateur sur un
runtime .NET basé sur WebAssembly. Blazor Les applications WebAssembly fonctionnent
de la même manière que les frameworks JavaScript front-end comme Angular ou React.
Toutefois, au lieu d’écrire JavaScript, vous écrivez C#. Le runtime .NET est téléchargé
avec l’application, ainsi que l’assembly d’application et toutes les dépendances requises.
Aucun plug-in ou extension de navigateur n’est requis.

Les assemblys téléchargés sont des assemblys .NET normaux, comme vous les utiliseriez
dans n’importe quelle autre application .NET. Étant donné que le runtime prend en
charge .NET Standard, vous pouvez utiliser des bibliothèques .NET Standard existantes
avec votre application BlazorWebAssembly. Toutefois, ces assemblys s’exécutent
toujours dans le bac à sable de sécurité du navigateur. Certaines fonctionnalités peuvent
lever un PlatformNotSupportedException, comme une tentative d’accéder au système
de fichiers ou d’ouvrir des connexions réseau arbitraires.

Lorsque l’application se charge, le runtime .NET est démarré et pointé vers l’assembly de
l’application. La logique de démarrage de l’application s’exécute et les composants
racines sont rendus. Blazor calcule les mises à jour de l’interface utilisateur en fonction
de la sortie rendue des composants. Les mises à jour du DOM sont ensuite appliquées.

Blazor Les applications WebAssembly s’exécutent purement côté client. Ces applications
peuvent être déployées sur des solutions d’hébergement de sites statiques, comme
GitHub Pages ou Azure Static Website Hosting. .NET n’est pas nécessaire sur le serveur.
Un lien profond vers des parties de l’application nécessite généralement une solution de
routage sur le serveur. La solution de routage redirige les demandes à la racine de
l’application. Par exemple, cette redirection peut être gérée à l’aide de règles de
réécriture d’URL dans IIS.

Pour obtenir tous les avantages de Blazor et du développement web .NET de pile
complète, hébergez votre application BlazorWebAssembly avec ASP.NET Core. En
utilisant .NET sur le client et le serveur, vous pouvez facilement partager du code et
créer votre application à l’aide d’un ensemble cohérent de langages, de frameworks et
d’outils. Blazor fournit des modèles pratiques pour configurer une solution qui contient
à la fois une application BlazorWebAssembly et un projet hôte ASP.NET Core. Lorsque la
solution est générée, les fichiers statiques générés à partir de l’application Blazor sont
hébergés par l’application ASP.NET Core avec le routage de secours déjà configuré.
Applications serveur Blazor
Rappelez-vous de la discussion d’architecture Blazor ; les composants Blazor rendent
leur sortie à une abstraction intermédiaire appelée RenderTree . L’infrastructure Blazor
compare ensuite ce qui a été rendu avec ce qui a été rendu précédemment. Les
différences sont appliquées au DOM. Les composants Blazor sont découplés de la façon
dont leur sortie rendue est appliquée. Par conséquent, les composants eux-mêmes n’ont
pas à s’exécuter dans le même processus que le processus mettant à jour l’interface
utilisateur. En fait, ils n’ont même pas à s’exécuter sur la même machine.

Dans les applications serveur Blazor, les composants s’exécutent sur le serveur au lieu du
côté client dans le navigateur. Les événements d’interface utilisateur qui se produisent
dans le navigateur sont envoyés au serveur via une connexion en temps réel. Les
événements sont distribués aux bonnes instances de composant. Le rendu des
composants, et la différence calculée de l’interface utilisateur, est sérialisé et envoyé au
navigateur où il est appliqué au DOM.

Le modèle d’hébergement serveur Blazor peut sembler familier si vous avez utilisé
ASP.NET AJAX et le contrôle UpdatePanel. Le contrôle UpdatePanel gère l’application de
mises à jour partielles de page en réponse au déclenchement d’événements sur la page.
Lors du déclenchement, le UpdatePanel demande une mise à jour partielle, puis
l’applique sans avoir à actualiser la page. L’état de l’interface utilisateur est géré à l’aide
de ViewState . Les applications serveur Blazor sont légèrement différentes en cela que
l’application nécessite une connexion active avec le client. En outre, l’état de l’interface
utilisateur est conservé sur le serveur. En dehors de ces différences, les deux modèles
sont conceptuellement similaires.

Comment choisir le modèle d’hébergement


Blazor approprié
Comme décrit dans la documentation du modèle d’hébergement Blazor, les différents
modèles d’hébergement Blazor ont des compromis différents.

Le modèle d’hébergement BlazorWebAssembly présente les avantages suivants :

Il n’existe aucune dépendance côté serveur .NET. L’application fonctionne


entièrement après le téléchargement sur le client.
Les ressources et les fonctionnalités clientes sont entièrement exploitées.
Le travail est déchargé du serveur vers le client.
Un serveur web ASP.NET Core n’est pas nécessaire pour héberger l’application. Les
scénarios de déploiement serverless sont possibles (par exemple, servir
l’application à partir d’un CDN).

Les inconvénients du modèle d’hébergement BlazorWebAssembly sont les suivants :

Les fonctionnalités du navigateur limitent l’application.


Du matériel client et des logiciels compatibles (par exemple, la prise en charge de
WebAssembly) sont requis.
La taille du téléchargement est plus grande et les applications prennent plus de
temps à se charger.
La prise en charge du runtime et de l’outil .NET est moins mature. Par exemple, il
existe des limitations dans la prise en charge et le débogage de .NET Standard.

À l’inverse, le modèle d’hébergement de serveur Blazor offre les avantages suivants :

La taille du téléchargement est beaucoup plus petite qu’une application côté client
et l’application se charge beaucoup plus rapidement.
L’application tire pleinement parti des fonctionnalités de serveur, notamment
l’utilisation de toutes les API compatibles .NET.
.NET sur le serveur est utilisé pour exécuter l’application. Ainsi, les outils .NET
existants, comme le débogage, fonctionnent comme prévu.
Les clients légers sont pris en charge. Par exemple, les applications côté serveur
fonctionnent avec les navigateurs qui ne prennent pas en charge WebAssembly et
sur les appareils limités en ressources.
La base de code .NET/C# de l’application, y compris le code du composant de
l’application, n’est pas servie aux clients.
Les inconvénients du modèle d’hébergement serveur Blazor sont les suivants :

Latence supérieure de l’interface utilisateur. Chaque interaction utilisateur implique


un tronçon réseau.
Il n’y a pas de prise en charge hors connexion. Si la connexion cliente échoue,
l’application cesse de fonctionner.
L’extensibilité est difficile pour les applications avec de nombreux utilisateurs. Le
serveur doit gérer plusieurs connexions clientes et gérer l’état du client.
Un serveur ASP.NET Core est requis pour servir l’application. Les scénarios de
déploiement serverless ne sont pas possibles. Par exemple, vous ne pouvez pas
servir l’application à partir d’un CDN.

La liste précédente de compromis peut être intimidante, mais votre modèle


d’hébergement peut être modifié ultérieurement. Quel que soit le modèle
d’hébergement Blazor sélectionné, le modèle de composant est identique. En principe,
les mêmes composants peuvent être utilisés avec l’un ou l’autre modèle d’hébergement.
Votre code d’application ne change pas ; toutefois, il est recommandé d’introduire des
abstractions afin que vos composants restent indépendants du modèle. Les abstractions
permettent à votre application d’adopter plus facilement un autre modèle
d’hébergement.

Déployer votre application


Les applications ASP.NET Web Forms sont généralement hébergées sur IIS sur un
ordinateur ou un cluster Windows Server. Les applications Blazor peuvent également :

Être hébergées sur IIS, en tant que fichiers statiques ou en tant qu’application
ASP.NET Core.
Tirer parti de la flexibilité d’ASP.NET Core pour être hébergées sur différentes
plateformes et infrastructures de serveur. Par exemple, vous pouvez héberger une
application Blazor à l’aide de Nginx ou Apache sur Linux. Pour plus d’informations
sur la publication et le déploiement d’applications Blazor, consultez la
Blazordocumentation Hébergement et déploiement.

Dans la section suivante, nous allons examiner la façon dont les projets pour
BlazorWebAssembly et les applications serveur Blazor sont configurés.

Précédent Suivant
Structure de projet pour les applications
Blazor
Article • 08/06/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor pour les développeurs ASP
NET Web Forms pour Azure, disponible dans la documentation .NET ou au format
PDF à télécharger gratuitement pour le lire hors connexion.

Télécharger le PDF

Malgré leurs différences importantes au niveau de la structure de projet, ASP.NET Web


Forms et Blazor partagent de nombreux concepts similaires. Ici, nous allons examiner la
structure d’un projet Blazor et le comparer à un projet ASP.NET Web Forms.

Pour créer votre première application Blazor, suivez les instructions des étapes de
démarrage de Blazor. Vous pouvez suivre les instructions pour créer une application
Blazor Server ou une application BlazorWebAssembly hébergée dans ASP.NET Core. À
l’exception de la logique spécifique au modèle d’hébergement, la plupart du code dans
les deux projets est identique.

Fichier projet
Les applications Blazor Server sont des projets .NET. Le fichier projet de l’application
Blazor Server est d’une simplicité à toute épreuve :

XML

<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>

</Project>

Le fichier projet d’une application BlazorWebAssembly semble légèrement plus


complexe (les numéros exacts des version peuvent varier) :

XML

<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly"
Version="7.0.0" />
<PackageReference
Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer"
Version="7.0.0" PrivateAssets="all" />
</ItemGroup>

</Project>

Le projet BlazorWebAssembly cible Microsoft.NET.Sdk.BlazorWebAssembly au lieu du


SDK Microsoft.NET.Sdk.Web parce qu’il s’exécute dans le navigateur sur un runtime .NET
basé sur WebAssembly. Vous ne pouvez pas installer .NET dans un navigateur web
comme vous le pouvez sur un serveur ou un ordinateur de développement. Par
conséquent, le projet référence le framework Blazor avec des références de package
individuelles.

En comparaison, un projet ASP.NET Web Forms par défaut compte près de 300 lignes de
code XML dans son fichier .csproj, dont la plupart liste explicitement les différents
fichiers de code et de contenu dans le projet. Depuis la publication de .NET 5, les
applications Blazor Server et BlazorWebAssembly peuvent facilement partager un
runtime unifié.

Bien qu’elles soient prises en charge, les références d’assembly individuelles sont moins
courantes dans les projets .NET. La plupart des dépendances de projet sont gérées
comme des références de package NuGet. Vous devez uniquement référencer les
dépendances de package de niveau supérieur dans les projets .NET. Les dépendances
transitives sont incluses automatiquement. Au lieu d’utiliser le fichier packages.config
que l’on trouve couramment dans les projets ASP.NET Web Forms pour référencer les
packages, les références de package sont ajoutées au fichier projet à l’aide de l’élément
<PackageReference> .

XML

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>

Point d’entrée
Le point d’entrée de l’application Blazor Server est défini dans le fichier Program.cs,
comme vous le verriez dans une application console. Lorsque l’application s’exécute, elle
crée et exécute une instance hôte web en utilisant les valeurs par défaut propres aux
applications web. L’hôte web gère le cycle de vie de l’application Blazor Server et
configure les services au niveau de l’hôte. Parmi ces services, citons par exemple la
configuration, la journalisation, l’injection de dépendances et le serveur HTTP. Ce code
est en grande partie réutilisable et reste souvent inchangé.

C#

using BlazorApp3.Areas.Identity;
using BlazorApp3.Data;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.


var connectionString =
builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options =>
options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<AuthenticationStateProvider,
RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
builder.Services.AddSingleton<WeatherForecastService>();

var app = builder.Build();

// Configure the HTTP request pipeline.


if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for
production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

Les applications BlazorWebAssembly définissent également un point d’entrée dans


Program.cs. Le code semble légèrement différent. Le code est similaire en ce sens qu’il
configure l’hôte d’application pour fournir les mêmes services de niveau hôte à
l’application. Toutefois, l’hôte d’application WebAssembly ne configure pas de serveur
HTTP parce qu’il s’exécute directement dans le navigateur.

Les applications Blazor n’utilisent pas de fichier Global.asax pour définir la logique de
démarrage de l’application. À la place, cette logique est contenue dans Program.cs ou
dans une classe Startup associée qui est référencée dans Program.cs. Dans les deux cas,
ce code est utilisé pour configurer l’application et tous les services spécifiques à
l’application.

Dans une application Blazor Server, le fichier Program.cs montré est utilisé pour
configurer le point de terminaison pour la connexion en temps réel utilisée par Blazor
entre les navigateurs clients et le serveur.

Dans une application BlazorWebAssembly, le fichier Program.cs définit les composants


racines de l’application et où ils doivent être rendus :

C#

using BlazorApp1;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new


Uri(builder.HostEnvironment.BaseAddress) });

await builder.Build().RunAsync();

Fichiers statiques
Contrairement aux projets ASP.NET Web Forms, les fichiers d’un projet Blazor ne
peuvent pas tous être demandés en tant que fichiers statiques. Seuls les fichiers du
dossier wwwroot sont adressables sur le web. Ce dossier est appelé « racine web » de
l’application. Tout ce qui se trouve en dehors de la racine web de l’application n’est pas
adressable sur le web. Cette configuration fournit un niveau de sécurité supplémentaire
qui empêche l’exposition accidentelle des fichiers projet sur le web.

Configuration
La configuration dans les applications ASP.NET Web Forms est généralement gérée à
l’aide d’un ou plusieurs fichiers web.config. Les applications Blazor n’ont généralement
pas de fichiers web.config. Si c’est le cas, le fichier est utilisé uniquement pour configurer
les paramètres spécifiques à IIS lorsqu’ils sont hébergés sur IIS. De leur côté, les
applications Blazor Server utilisent les abstractions de configuration ASP.NET Core.
(Actuellement, les applications BlazorWebAssembly ne prennent pas en charge les
mêmes abstractions de configuration, mais ce sera peut-être une fonctionnalité qui sera
ajoutée plus tard.) Par exemple, l’application Blazor Server par défaut stocke certains
paramètres dans appsettings.json.

JSON

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
Vous en apprendrez plus sur la configuration dans les projets ASP.NET Core dans la
section Configuration.

Composants Razor
La plupart des fichiers des projets Blazor sont des fichiers .razor. Razor est un langage
de création de modèles basé sur HTML et C# qui est utilisé pour générer
dynamiquement l’interface utilisateur web. Les fichiers .razor définissent les composants
qui constituent l’interface utilisateur de l’application. Les composants sont en grande
partie identiques pour les applications Blazor Server et BlazorWebAssembly. Les
composants dans Blazor sont analogues aux contrôles utilisateur dans ASP.NET Web
Forms.

Chaque fichier de composant Razor est compilé dans une classe .NET lors de la
génération du projet. La classe générée capture l’état, la logique de rendu, les méthodes
de cycle de vie, les gestionnaires d’événements et autres logiques du composant. Vous
en apprendrez plus sur la création de composants dans la section Création de
composants d’interface utilisateur réutilisables avec Blazor.

Les fichiers _Imports.razor ne sont pas des fichiers de composants Razor. En fait, ils
définissent un ensemble de directives Razor à importer dans les autres fichiers .razor
dans le même dossier et dans ses sous-dossiers. Par exemple, un fichier _Imports.razor
est un moyen conventionnel d’ajouter des directives using pour les espaces de noms
couramment utilisés :

razor

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using BlazorApp1
@using BlazorApp1.Shared

Pages
Où sont les pages dans les applications Blazor ? Blazor ne définit pas d’extension de
fichier distincte pour les pages adressables, comme les fichiers .aspx dans les
applications ASP.NET Web Forms. En fait, les pages sont définies en affectant des routes
aux composants. Une route est généralement attribuée en utilisant la directive Razor
@page . Par exemple, le composant Counter créé dans le fichier Pages/Counter.razor
définit la route suivante :

razor

@page "/counter"

Le routage dans Blazor est géré côté client, et non sur le serveur. Lorsque l’utilisateur
circule dans le navigateur, Blazor intercepte la navigation, puis rend le composant avec
la route correspondante.

Actuellement, les routes de composants ne sont pas déduites par l’emplacement du


fichier du composant, comme elles le sont avec les pages .aspx ou ASP.NET Core Razor
Pages. Cette fonctionnalité sera peut-être ajoutée plus tard. Chaque route doit être
spécifiée explicitement sur le composant. Le stockage des composants routables dans
un dossier Pages n’a pas de signification particulière, c’est par pure convention.

Vous en apprendrez plus sur le routage dans Blazor dans la section Pages, routage et
mises en page.

Layout
Dans les applications ASP.NET Web Forms, une mise en page commune est gérée à
l’aide de pages maîtres (Site.Master). Dans les applications Blazor, la mise en page est
gérée avec des composants de mise en page (Shared/MainLayout.razor). Les
composants de mise en page sont abordés plus en détail dans la section Page, routage
et mises en page.

Amorcer Blazor
Pour amorcer Blazor, l’application doit :

Spécifier où, dans la page, le composant racine (App.Razor) doit être rendu.
Ajouter le script du framework Blazor correspondant.

Dans l’application Blazor Server, la page hôte du composant racine est définie dans le
fichier _Host.cshtml. Ce fichier définit une page Razor, pas un composant. Les pages
Razor utilisent la syntaxe Razor pour définir une page adressable au serveur, très
similaire à une page .aspx.

razor
@page "/"
@namespace BlazorApp3.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = "_Layout";
}

<component type="typeof(App)" render-mode="ServerPrerendered" />

L’attribut render-mode est utilisé pour définir où un composant de niveau racine doit
être rendu. L’option RenderMode indique la manière dont le composant doit être rendu.
Le tableau suivant présente les options RenderMode prises en charge.

Option Description

RenderMode.Server Rendue de manière interactive une fois qu’une connexion au


navigateur est établie

RenderMode.ServerPrerendered D’abord pré-rendue, puis rendue de manière interactive

RenderMode.Static Rendue en tant que contenu statique

Le fichier _Layout.cshtml contient le code HTML par défaut de l’application et de ses


composants.

razor

@using Microsoft.AspNetCore.Components.Web
@namespace BlazorApp3.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<link href="BlazorApp3.styles.css" rel="stylesheet" />
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>
<body>
@RenderBody()

<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond
until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for
details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>

<script src="_framework/blazor.server.js"></script>
</body>
</html>

La référence de script à _framework/blazor.server.js établit la connexion en temps réel au


serveur, puis traite toutes les interactions utilisateur et les mises à jour de l’interface
utilisateur.

Dans l’application BlazorWebAssembly, la page hôte est un fichier HTML statique simple
sous wwwroot/index.html. L’élément <div> avec l’ID appelé app est utilisé pour indiquer
où le composant racine doit être rendu.

HTML

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0,
maximum-scale=1.0, user-scalable=no" />
<title>BlazorApp1</title>
<base href="/" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
<link href="BlazorApp1.styles.css" rel="stylesheet" />
</head>

<body>
<div id="app">Loading...</div>

<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
</body>

</html>
Le composant racine à rendre est spécifié dans le fichier Program.cs de l’application avec
la flexibilité nécessaire pour inscrire les services via l’injection de dépendances. Pour plus
d’informations, consultez Injection de dépendances Blazor ASP.NET Core.

C#

var builder = WebAssemblyHostBuilder.CreateDefault(args);


builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

Sortie de la génération
Lorsqu’un projet Blazor est généré, tous les fichiers de composant et de code Razor sont
compilés dans un seul assembly. Contrairement aux projets ASP.NET Web Forms, Blazor
ne prend pas en charge la compilation du runtime de la logique d’interface utilisateur.

Exécuter l’application avec le Rechargement à


chaud
Pour exécuter l’application Blazor Server, appuyez sur F5 dans Visual Studio pour
qu’elle s’exécute avec le débogueur attaché, ou Ctrl + F5 pour qu’elle s’exécute sans
le débogueur attaché.

Pour exécuter l’application BlazorWebAssembly, choisissez l’une des approches


suivantes :

Exécuter le projet client directement à l’aide du serveur de développement.


Exécuter le projet serveur lors de l’hébergement de l’application avec ASP.NET
Core.

Les applications BlazorWebAssembly peuvent être déboguées à la fois dans le


navigateur et dans Visual Studio. Pour plus de détails, consultez Déboguer ASP.NET Core
BlazorWebAssembly.

Les applications Blazor Server et BlazorWebAssembly prennent en charge le


Rechargement à chaud dans Visual Studio. Le Rechargement à chaud est une
fonctionnalité qui met automatiquement à jour les modifications apportées à une
application Blazor en direct, dans le navigateur. Vous pouvez désactiver le
Rechargement à chaud s’il est activé à partir de son icône dans la barre d’outils :
La sélection de l’accent circonflexe à côté de l’icône révèle des options supplémentaires.
Vous pouvez activer ou désactiver le Rechargement à chaud, redémarrer l’application et
choisir si le Rechargement à chaud doit ou non se produire chaque fois qu’un fichier est
enregistré.

Vous pouvez également accéder à des options de configuration supplémentaires. La


boîte de dialogue de configuration vous permet de spécifier si le Rechargement à chaud
doit être activé lors du débogage (avec Modifier et continuer), lors d’un démarrage sans
débogage ou lors de l’enregistrement d’un fichier.
La « boucle interne du développeur » a été considérablement simplifiée avec le
Rechargement à chaud. Sans le Rechargement à chaud, un développeur Blazor devrait
normalement redémarrer et réexécuter l’application après chaque modification, en
accédant à la partie appropriée de l’application. Avec le Rechargement à chaud, les
modifications peuvent être apportées à l’application en cours d’exécution sans avoir à
redémarrer dans la plupart des cas. Le Rechargement à chaud conserve même l’état des
pages, donc il n’est pas nécessaire de réentrer les valeurs de formulaire ou de récupérer
l’application là où vous en avez besoin.

Précédent Suivant
Démarrage des applications
Article • 10/05/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor for ASP NET Web Forms
Developers for Azure (Blazor pour les développeurs ASP NET Web Forms pour
Azure), disponible sur la documentation .NET ou en tant que PDF téléchargeable
gratuitement qui peut être lu hors connexion.

Télécharger le PDF

Les applications écrites pour ASP.NET ont généralement un fichier global.asax.cs qui
définit l’événement Application_Start qui contrôle les services configurés et mis à
disposition pour le rendu HTML et le traitement .NET. Ce chapitre explique les légères
différences entre ASP.NET Core et Blazor Server.

Application_Start et Web Forms


La méthode de formulaires web par défaut Application_Start a évolué au fil des ans
pour gérer de nombreuses tâches de configuration. Un nouveau projet web forms avec
le modèle par défaut dans Visual Studio 2022 contient désormais la logique de
configuration suivante :

RouteConfig - Routage d’URL d’application


BundleConfig - Regroupement et minimisation CSS et JavaScript

Chacun de ces fichiers individuels réside dans le dossier App_Start et ne s’exécute


qu’une seule fois au début de notre application. RouteConfig dans le modèle de projet
par défaut ajoute FriendlyUrlSettings pour les web forms afin de permettre aux URL
d’application d’omettre l’extension de fichier .ASPX . Le modèle par défaut contient
également une directive qui fournit des codes d’état de redirection HTTP permanents
(HTTP 301) pour les pages .ASPX vers l’URL conviviale avec le nom de fichier qui omet
l’extension.

Avec ASP.NET Core et Blazor, ces méthodes sont simplifiées et consolidées dans la
classe Startup ou sont éliminées au profit des technologies web courantes.

Structure de démarrage du serveur Blazor


Les applications Blazor Server résident sur ASP.NET Core 3.0 ou version ultérieure. Le
applications web ASP.NET Core sont configurées dans Program.cs ou par le biais d’une
paire de méthodes dans la classe Startup.cs . Un exemple de fichier Program.cs est
illustré ci-dessous :

C#

using BlazorApp1.Data;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.


builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();

var app = builder.Build();

// Configure the HTTP request pipeline.


if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for
production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

Les services requis de l’application sont ajoutés à la collection Services de l’instance


WebApplicationBuilder . C’est ainsi que les différents services d’infrastructure ASP.NET
Core sont configurés avec le conteneur d’injection de dépendances intégré de
l’infrastructure. Les différentes méthodes builder.Services.Add* ajoutent des services
qui activent des fonctionnalités telles que l’authentification, Razor Pages, le routage du
contrôleur MVC, SignalR et les interactions Blazor Server, entre autres. Cette méthode
n’était pas nécessaire dans les web forms, car l’analyse et la gestion des fichiers ASPX,
ASCX, ASHX et ASMX étaient définis en référençant ASP.NET dans le fichier de
configuration web.config. Des informations supplémentaires sur l’injection de
dépendances dans ASP.NET Core sont disponibles dans la documentation en ligne.

Une fois le app généré par le builder , le reste des appels sur app configurent son
pipeline HTTP. Avec ces appels, nous déclarons de haut en bas le Middleware qui gérera
chaque requête envoyée à notre application. La plupart de ces fonctionnalités de la
configuration par défaut ont été réparties dans les fichiers de configuration de web
forms et se trouvent désormais à un seul endroit pour pouvoir s’y référer facilement.

De même, la configuration de la page d’erreur personnalisée n’est plus placée dans un


fichier web.config , mais elle est maintenant configurée pour toujours être affichée si
l’environnement d’application n’est pas étiqueté Development . En outre, ASP.NET Core
applications sont désormais configurées pour traiter des pages sécurisées avec TLS par
défaut avec l’appel de méthode UseHttpsRedirection .

Ensuite, un appel de méthode de configuration inattendu est effectué à UseStaticFiles .


Dans ASP.NET Core, la prise en charge des requêtes de fichiers statiques (comme les
fichiers JavaScript, CSS et image) doit être activée explicitement, et seuls les fichiers du
dossier wwwroot de l’application sont adressables publiquement par défaut.

La ligne suivante est la première qui réplique l’une des options de configuration à partir
des web forms : UseRouting . Cette méthode ajoute le routeur ASP.NET Core au pipeline
et peut être configuré ici ou dans les fichiers individuels vers lesquels il peut envisager
d’effectuer le routage. Vous trouverez plus d’informations sur la configuration du
routage dans la section Routage.

Les appels app.Map* finaux de cette section définissent les points de terminaison
qu’écoute ASP.NET Core. Ces itinéraires correspondent aux emplacements accessibles
sur le web auxquels vous pouvez accéder sur le serveur web et sur lesquels vous pouvez
recevoir du contenu géré par .NET que vous avez retourné. La première entrée
MapBlazorHub configure un hub SignalR à utiliser pour fournir la connexion en temps

réel et persistante au serveur où sont gérés l’état et le rendu des composants Blazor.
L’appel de méthode MapFallbackToPage indique l’emplacement accessible sur le web de
la page qui démarre l’application Blazor et configure également l’application pour gérer
les requêtes de liaison approfondie côté client. Vous verrez cette fonctionnalité si vous
ouvrez un navigateur et accédez directement à l’itinéraire géré par Blazor dans votre
application, comme /counter dans le modèle de projet par défaut. La requête est gérée
par la page de secours _Host.cshtml, qui exécute ensuite le routeur Blazor et affiche la
page du compteur.

La dernière ligne démarre l’application, ce qui n’était pas nécessaire dans les web forms
(car IIS était utilisé pour l’exécution).

Mise à niveau du processus BundleConfig


Les technologies de regroupement de ressources telles que les feuilles de style CSS et
les fichiers JavaScript ont considérablement évolué, avec le développement d’autres
technologies offrant des outils et des techniques qui évoluent rapidement pour la
gestion de ces ressources. À cette fin, nous vous recommandons d’utiliser un outil en
ligne de commande Node tel que Grunt / Gulp / WebPack pour empaqueter vos
ressources statiques.

Les outils en ligne de commande Grunt, Gulp et WebPack et leurs configurations


associées peuvent être ajoutés à votre application et ASP.NET Core ignore
silencieusement ces fichiers pendant le processus de génération de l’application. Vous
pouvez ajouter un appel pour exécuter leurs tâches en ajoutant un Target dans votre
fichier de projet avec une syntaxe similaire à ce qui suit pour déclencher un script Gulp
et la cible min à l’intérieur de ce script :

XML

<Target Name="MyPreCompileTarget" BeforeTargets="Build">


<Exec Command="gulp min" />
</Target>

Pour plus d’informations sur les deux stratégies de gestion de vos fichiers CSS et
JavaScript, consultez la documentation Regrouper et minimiser les ressources statiques
dans ASP.NET Core.

Précédent Suivant
Créer des composants d’interface
utilisateur réutilisables avec Blazor
Article • 08/06/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor pour les développeurs ASP
NET Web Forms pour Azure, disponible dans la documentation .NET ou au format
PDF à télécharger gratuitement pour le lire hors connexion.

Télécharger le PDF

L’un des avantages de ASP.NET Web Forms est qu’il permet d’encapsuler des éléments
de code d’interface utilisateur (IU) réutilisables dans des contrôles IU réutilisables. Des
contrôles utilisateur personnalisés peuvent être définis par balisage à l’aide de fichiers
.ascx. Vous pouvez également créer des contrôles serveur élaborés dans le code avec
prise en charge complète du concepteur.

Blazor prend également en charge l’encapsulation de l’interface utilisateur par le biais


de composants. Un composant :

Est un segment autonome de l’interface utilisateur.


Conserve son propre état et sa logique de rendu.
Peut définir des gestionnaires d’événements d’interface utilisateur, lier des
données d’entrée et gérer son propre cycle de vie.
Est généralement défini dans un fichier .razor à l’aide de la syntaxe Razor.

Présentation de Razor
Razor est un langage de balisage léger basé sur HTML et C#. Avec Razor, vous pouvez
effectuer une transition transparente entre le balisage et le code C# pour définir votre
logique de rendu de composant. Lorsque le fichier .razor est compilé, la logique de
rendu est capturée de manière structurée dans une classe .NET. Le nom de la classe
compilée est extrait du nom de fichier .razor. L’espace de noms est extrait de l’espace de
noms par défaut pour le projet et du chemin du dossier, ou vous pouvez spécifier
explicitement l’espace de noms à l’aide de la directive @namespace (plus d’informations
sur les directives Razor ci-dessous).

La logique de rendu d’un composant est créée à l’aide du balisage HTML normal avec
une logique dynamique ajoutée à l’aide de C#. Le caractère @ est utilisé pour passer à
C#. Razor est généralement intelligent pour savoir quand vous êtes revenu au HTML. Par
exemple, le composant suivant affiche une balise <p> avec l’heure actuelle :

razor

<p>@DateTime.Now</p>

Pour spécifier explicitement le début et la fin d’une expression C#, utilisez des
parenthèses :

razor

<p>@(DateTime.Now)</p>

Razor facilite également l’utilisation du flux de contrôle C# dans votre logique de rendu.
Par exemple, vous pouvez afficher du code HTML de manière conditionnelle comme suit
:

razor

@if (value % 2 == 0)
{
<p>The value was even.</p>
}

Vous pouvez également générer une liste d’éléments à l’aide d’une boucle C# foreach
normale comme suit :

razor

<ul>
@foreach (var item in items)
{
<li>@item.Text</li>
}
</ul>
Les directives Razor, comme les directives dans ASP.NET Web Forms, contrôlent de
nombreux aspects de la compilation d’un composant Razor. Les exemples incluent les
éléments suivants du composant :

Espace de noms
Classe de base
Interfaces implémentées
Paramètres génériques
Espaces de noms importés
Itinéraires

Les directives Razor commencent par le caractère @ et sont généralement utilisées au


début d’une nouvelle ligne au début du fichier. Par exemple, la directive @namespace
définit l’espace de noms du composant :

razor

@namespace MyComponentNamespace

Le tableau suivant récapitule les différentes directives Razor utilisées dans Blazor et leurs
équivalents ASP.NET Web Forms, s’ils existent.

Directive Description Exemple Équivalent Web Forms

@attribute Ajoute un attribut au @attribute Aucun


niveau de la classe au [Authorize]
composant

@code Ajoute des membres de @code { ... } <script runat="server">...


classe au composant </script>

@implements Implémente l’interface @implements Utiliser code-behind


spécifiée IDisposable

@inherits Hérite de la classe de @inherits <%@ Control


base spécifiée MyComponentBase Inherits="MyUserControlBase"
%>

@inject Injecte un service dans @inject IJSRuntime Aucun


le composant JS

@layout Spécifie un composant @layout MainLayout <%@ Page


de disposition pour le MasterPageFile="~/Site.Master"
composant %>
Directive Description Exemple Équivalent Web Forms

@namespace Définit l’espace de @namespace Aucun


noms du composant MyNamespace

@page Spécifie l’itinéraire du @page <%@ Page %>


composant "/product/{id}"

@typeparam Spécifie un paramètre @typeparam TItem Utiliser code-behind


de type générique pour
le composant

@using Spécifie un espace de @using Ajouter un espace de noms


noms à insérer dans MyComponentNamespace dans web.config
l’étendue

Les composants Razor utilisent également largement les attributs de directive sur les
éléments pour contrôler différents aspects de la façon dont les composants sont
compilés (gestion des événements, liaison de données, références d’éléments & de
composant, etc.). Les attributs de directive suivent tous une syntaxe générique
commune où les valeurs entre parenthèses sont facultatives :

razor

@directive(-suffix(:name))(="value")

Le tableau suivant récapitule les différents attributs des directives Razor utilisés dans
Blazor.

Attribut Description Exemple

@attributes Génère le rendu d’un dictionnaire d’attributs <input


@attributes="ExtraAttributes"
/>

@bind Crée une liaison de données bidirectionnelle <input @bind="username"


@bind:event="oninput" />

@on{event} Ajoute un gestionnaire d’événements pour <button


l’événement spécifié @onclick="IncrementCount">Click
me!</button>

@key Spécifie une clé à utiliser par l’algorithme <DetailsEditor @key="person"


différentiel pour conserver des éléments dans Details="person.Details" />
une collection
Attribut Description Exemple

@ref Capture une référence au composant ou à <MyDialog @ref="myDialog" />


l’élément HTML

Les différents attributs de directive utilisés par Blazor ( @onclick , @bind , @ref et ainsi de
suite) sont couverts dans les sections ci-dessous et les chapitres ultérieurs.

La plupart des syntaxes utilisées dans les fichiers .aspx et .ascx ont des syntaxes
parallèles dans Razor. Vous trouverez ci-dessous une comparaison simple des syntaxes
pour ASP.NET Web Forms et Razor.

Fonctionnalité Web Forms Syntaxe Razor Syntaxe

Directives <%@ [directive] <%@ Page %> @[directive] @page


%>

Blocs de code <% %> <% int x = 123; @{ } @{ int x = 123; }


%>

Expressions <%: %> <%:DateTime.Now Implicite : @ @DateTime.Now


(HTML- %> Explicite : @() @(DateTime.Now)
encoded)

Commentaires <%-- --%> <%-- Commented - @* *@ @* Commented *@


-%>

Liaison de <%# %> <%# Bind("Name") @bind <input


données %> @bind="username" />

Pour ajouter des membres à la classe de composant Razor, utilisez la directive @code .
Cette technique est similaire à l’utilisation d’un bloc <script runat="server">...
</script> dans un contrôle utilisateur ou une page ASP.NET Web Forms.

razor

@code {
int count = 0;

void IncrementCount()
{
count++;
}
}

Étant donné que Razor est basé sur C#, il doit être compilé à partir d’un projet C#
(.csproj). Vous ne pouvez pas compiler les fichiers .razor à partir d’un projet Visual Basic
(.vbproj). Vous pouvez toujours référencer des projets Visual Basic à partir de votre
projet Blazor. L’inverse est également vrai.

Pour obtenir une référence complète de syntaxe Razor, consultez la Référence de


syntaxe Razor pour ASP.NET Core.

Utiliser des composants


Outre le code HTML normal, les composants peuvent également utiliser d’autres
composants dans le cadre de leur logique de rendu. La syntaxe d’utilisation d’un
composant dans Razor est similaire à l’utilisation d’un contrôle utilisateur dans une
application ASP.NET Web Forms. Les composants sont spécifiés à l’aide d’une balise
d’élément qui correspond au nom de type du composant. Par exemple, vous pouvez
ajouter un composant Counter comme suit :

razor

<Counter />

Contrairement à ASP.NET Web Forms, les composants dans Blazor :

N’utilisez pas de préfixe d’élément (par exemple asp: ).


N’exigez pas besoin d’inscription sur la page ou dans le web.config.

Pensez aux composants Razor comme vous le feriez pour les types .NET, car c’est
exactement ce qu’ils sont. Si l’assembly contenant le composant est référencé, le
composant est disponible pour utilisation. Pour placer l’espace de noms du composant
dans l’étendue, appliquez la directive @using :

razor

@using MyComponentLib

<Counter />

Comme indiqué dans les projets Blazor par défaut, il est courant de placer des directives
@using dans un fichier _Imports.razor afin de les importer dans tous les fichiers .razor

dans le même répertoire et dans les répertoires enfants.

Si l’espace de noms d’un composant n’est pas dans l’étendue, vous pouvez spécifier un
composant à l’aide de son nom de type complet, comme vous pouvez le faire en C# :

razor
<MyComponentLib.Counter />

Modifier le titre de la page à partir des


composants
Lors de la création d’applications de style SPA, il est courant que les parties d’une page
se rechargent sans recharger la page entière. Malgré cela, il peut être utile de faire en
sorte que le titre de la page change en fonction du composant actuellement chargé.
Pour ce faire, incluez la balise <PageTitle> dans la page Razor du composant :

razor

@page "/"
<PageTitle>Home</PageTitle>

Le contenu de cet élément peut être dynamique, par exemple en montrant le nombre
actuel de messages :

razor

<PageTitle>@MessageCount messages</PageTitle>

Notez que si plusieurs composants d’une page particulière incluent des balises
<PageTitle> , seul le dernier sera affiché (car chacun remplacera le précédent).

Paramètres de composant
Dans ASP.NET Web Forms, vous pouvez envoyer des paramètres et des données vers
des contrôles à l’aide de propriétés publiques. Ces propriétés peuvent être définies dans
le balisage à l’aide d’attributs ou définies directement dans le code. Les composants
Razor fonctionnent de manière similaire, bien que les propriétés des composants
doivent également être marquées avec l’attribut [Parameter] pour être considérés
comme des paramètres de composant.

Le composant Counter suivant définit un paramètre de composant appelé


IncrementAmount qui peut être utilisé pour spécifier la quantité par laquelle Counter doit
être incrémenté à chaque clic sur le bouton.

razor
<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
int currentCount = 0;

[Parameter]
public int IncrementAmount { get; set; } = 1;

void IncrementCount()
{
currentCount+=IncrementAmount;
}
}

Pour spécifier un paramètre de composant dans Blazor, utilisez un attribut comme vous
le feriez dans ASP.NET Web Forms :

razor

<Counter IncrementAmount="10" />

Paramètres de chaîne de requête


Les composants Razor peuvent également tirer parti des valeurs de la chaîne de requête
de la page sur laquelle ils sont rendus en tant que source de paramètre. Pour activer
cela, ajoutez l’attribut [SupplyParameterFromQuery] au paramètre. Par exemple, la
définition de paramètre suivante obtient sa valeur à partir de la requête sous la forme ?
IncBy=2 :

C#

[Parameter]
[SupplyParameterFromQuery(Name = "IncBy")]
public int IncrementAmount { get; set; } = 1;

Si vous ne fournissez pas de code personnalisé Name dans l’attribut


[SupplyParameterFromQuery] , par défaut, il correspondra au nom de la propriété

( IncrementAmount dans ce cas).

Composants et limites d’erreur


Par défaut, les applications Blazor détectent les exceptions non gérées et affichent un
message d’erreur en bas de la page sans détails supplémentaires. Pour limiter les parties
de l’application qui sont affectées par une erreur non gérée, par exemple pour limiter
l’impact à un seul composant, la balise <ErrorBoundary> peut être encapsulée autour
des déclarations de composant.

Par exemple, pour vous protéger contre les exceptions possibles levées à partir du
composant Counter , déclarez-le dans un <ErrorBoundary> et spécifiez éventuellement
un message à afficher s’il existe une exception :

razor

<ErrorBoundary>
<ChildContent>
<Counter />
</ChildContent>
<ErrorContent>
Oops! The counter isn't working right now; please try again later.
</ErrorContent>
</ErrorBoundary>

Si vous n’avez pas besoin de spécifier de contenu d’erreur personnalisé, vous pouvez
simplement encapsuler le composant directement :

razor

<ErrorBoundary>
<Counter />
</ErrorBoundary>

Un message par défaut indiquant « Une erreur s’est produite » s’affiche si une exception
non gérée se produit dans le composant encapsulé.

Gestionnaires d’événements
ASP.NET Web Forms et Blazor fournissent tous deux un modèle de programmation basé
sur les événements pour gérer les événements d’interface utilisateur. Les exemples de
ces événements incluent les clics de bouton et l’entrée de texte. Dans ASP.NET Web
Forms, vous utilisez des contrôles de serveur HTML pour gérer les événements
d’interface utilisateur exposés par le DOM, ou vous pouvez gérer les événements
exposés par les contrôles de serveur web. Les événements sont exposés sur le serveur
via des demandes de publication de formulaire. Prenons l’exemple de clic sur le bouton
Web Forms suivant :
Counter.ascx

ASP.NET (C#)

<asp:Button ID="ClickMeButton" runat="server" Text="Click me!"


OnClick="ClickMeButton_Click" />

Counter.ascx.cs

C#

public partial class Counter : System.Web.UI.UserControl


{
protected void ClickMeButton_Click(object sender, EventArgs e)
{
Console.WriteLine("The button was clicked!");
}
}

Dans Blazor, vous pouvez inscrire des gestionnaires pour les événements d’interface
utilisateur DOM directement à l’aide d’attributs de directive de la forme @on{event} .
L’espace réservé {event} représente le nom de l’événement. Par exemple, vous pouvez
écouter les clics de bouton comme suit :

razor

<button @onclick="OnClick">Click me!</button>

@code {
void OnClick()
{
Console.WriteLine("The button was clicked!");
}
}

Les gestionnaires d’événements peuvent accepter un argument facultatif spécifique à


l’événement pour fournir plus d’informations sur l’événement. Par exemple, les
événements de souris peuvent prendre un argument MouseEventArgs , mais il n’est pas
obligatoire.

razor

<button @onclick="OnClick">Click me!</button>

@code {
void OnClick(MouseEventArgs e)
{
Console.WriteLine($"Mouse clicked at {e.ScreenX}, {e.ScreenY}.");
}
}

Au lieu de faire référence à un groupe de méthodes pour un gestionnaire d’événements,


vous pouvez utiliser une expression lambda. Une expression lambda vous permet de
fermer d’autres valeurs dans l’étendue.

razor

@foreach (var buttonLabel in buttonLabels)


{
<button @onclick="() => Console.WriteLine($"The {buttonLabel} button was
clicked!")">@buttonLabel</button>
}

Les gestionnaires d’événements peuvent s’exécuter de manière synchrone ou


asynchrone. Par exemple, le gestionnaire d’événements OnClick suivant s’exécute de
manière asynchrone :

razor

<button @onclick="OnClick">Click me!</button>

@code {
async Task OnClick()
{
var result = await Http.GetAsync("api/values");
}
}

Une fois qu’un événement est géré, le composant est rendu pour tenir compte des
modifications d’état du composant. Avec les gestionnaires d’événements asynchrones, le
composant est rendu immédiatement une fois l’exécution du gestionnaire terminée. Le
composant est rendu à nouveau une fois l’opération asynchrone Task terminée. Ce
mode d’exécution asynchrone permet d’afficher une interface utilisateur appropriée
alors que le Task asynchrone est toujours en cours.

razor

<button @onclick="ShowMessage">Get message</button>

@if (showMessage)
{
@if (message == null)
{
<p><em>Loading...</em></p>
}
else
{
<p>The message is: @message</p>
}
}

@code
{
bool showMessage = false;
string message;

public async Task ShowMessage()


{
showMessage = true;
message = await MessageService.GetMessageAsync();
}
}

Les composants peuvent également définir leurs propres événements en définissant un


paramètre de composant de type EventCallback<TValue> . Les rappels d’événements
prennent en charge toutes les variantes des gestionnaires d’événements d’interface
utilisateur DOM : arguments facultatifs, synchrones ou asynchrones, groupes de
méthodes ou expressions lambda.

razor

<button class="btn btn-primary" @onclick="OnClick">Click me!</button>

@code {
[Parameter]
public EventCallback<MouseEventArgs> OnClick { get; set; }
}

Liaison de données
Blazor fournit un mécanisme simple pour lier des données d’un composant d’interface
utilisateur à l’état du composant. Cette approche diffère des fonctionnalités d’ASP.NET
Web Forms pour lier des données de sources de données aux contrôles d’interface
utilisateur. Nous aborderons la gestion des données provenant de différentes sources
de données dans la section Gestion des données.

Pour créer une liaison de données bidirectionnelle d’un composant d’interface utilisateur
à l’état du composant, utilisez l’attribut de directive @bind . Dans l’exemple suivant, la
valeur de la case à cocher est liée au champ isChecked .
razor

<input type="checkbox" @bind="isChecked" />

@code {
bool isChecked;
}

Lorsque le composant est rendu, la valeur de la case à cocher est définie sur la valeur du
champ isChecked . Lorsque l’utilisateur bascule la case à cocher, l’événement onchange
est déclenché et le champ isChecked est défini sur la nouvelle valeur. La syntaxe @bind
dans ce cas équivaut au balisage suivant :

razor

<input value="@isChecked" @onchange="(UIChangeEventArgs e) => isChecked =


e.Value" />

Pour modifier l’événement utilisé pour la liaison, utilisez l’attribut @bind:event .

razor

<input @bind="text" @bind:event="oninput" />


<p>@text</p>

@code {
string text;
}

Les composants peuvent également prendre en charge la liaison de données sur leurs
paramètres. Pour lier des données, définissez un paramètre de rappel d’événement
portant le même nom que le paramètre pouvant être lié. Le suffixe « Changed » est
ajouté au nom.

PasswordBox.razor

razor

Password: <input
value="@Password"
@oninput="OnPasswordChanged"
type="@(showPassword ? "text" : "password")" />

<label><input type="checkbox" @bind="showPassword" />Show password</label>

@code {
private bool showPassword;
[Parameter]
public string Password { get; set; }

[Parameter]
public EventCallback<string> PasswordChanged { get; set; }

private Task OnPasswordChanged(ChangeEventArgs e)


{
Password = e.Value.ToString();
return PasswordChanged.InvokeAsync(Password);
}
}

Pour chaîner une liaison de données à un élément d’interface utilisateur sous-jacent,


définissez la valeur et gérez l’événement directement sur l’élément d’interface utilisateur
au lieu d’utiliser l’attribut @bind .

Pour établir une liaison à un paramètre de composant, utilisez un attribut @bind-


{Parameter} pour spécifier le paramètre auquel vous souhaitez vous lier.

razor

<PasswordBox @bind-Password="password" />

@code {
string password;
}

Modifications d'état
Si l’état du composant a changé en dehors d’un événement d’interface utilisateur
normal ou d’un rappel d’événement, le composant doit signaler manuellement qu’il doit
être rendu à nouveau. Pour signaler que l’état d’un composant a changé, appelez la
méthode StateHasChanged sur le composant.

Dans l’exemple ci-dessous, un composant affiche un message provenant d’un service


AppState qui peut être mis à jour par d’autres parties de l’application. Le composant

inscrit sa méthode StateHasChanged avec l’événement AppState.OnChange afin que le


composant soit rendu chaque fois que le message est mis à jour.

C#

public class AppState


{
public string Message { get; }
// Lets components receive change notifications
public event Action OnChange;

public void UpdateMessage(string message)


{
Message = message;
NotifyStateChanged();
}

private void NotifyStateChanged() => OnChange?.Invoke();


}

razor

@inject AppState AppState

<p>App message: @AppState.Message</p>

@code {
protected override void OnInitialized()
{
AppState.OnChange += StateHasChanged
}
}

Cycle de vie des composants


Le framework ASP.NET Web Forms a des méthodes de cycle de vie bien définies pour les
modules, les pages et les contrôles. Par exemple, le contrôle suivant implémente des
gestionnaires d’événements pour les événements de cycle de vie Init , Load et UnLoad :

Counter.ascx.cs

C#

public partial class Counter : System.Web.UI.UserControl


{
protected void Page_Init(object sender, EventArgs e) { ... }
protected void Page_Load(object sender, EventArgs e) { ... }
protected void Page_UnLoad(object sender, EventArgs e) { ... }
}

Les composants Razor possèdent aussi un cycle de vie bien défini. Le cycle de vie d’un
composant peut être utilisé pour initialiser l’état du composant et implémenter des
comportements de composant avancés.
Toutes les méthodes de cycle de vie des composants de Blazor ont des versions
synchrones et asynchrones. Le rendu des composants est synchrone. Vous ne pouvez
pas exécuter de logique asynchrone dans le cadre du rendu du composant. Toute
logique asynchrone doit s’exécuter dans le cadre d’une méthode de cycle de vie async .

OnInitialized
Les méthodes OnInitialized et OnInitializedAsync sont utilisées pour initialiser le
composant. Un composant est généralement initialisé après son rendu. Une fois qu’un
composant est initialisé, il peut être rendu plusieurs fois avant qu’il ne soit finalement
supprimé. La méthode OnInitialized est similaire à l’événement Page_Load dans les
pages et contrôles ASP.NET Web Forms.

C#

protected override void OnInitialized() { ... }


protected override async Task OnInitializedAsync() { await ... }

OnParametersSet
Les méthodes OnParametersSet et OnParametersSetAsync sont appelées lorsqu’un
composant a reçu des paramètres de son parent et que la valeur est affectée aux
propriétés. Ces méthodes sont exécutées après l’initialisation des composants et chaque
fois que le composant est rendu.

C#

protected override void OnParametersSet() { ... }


protected override async Task OnParametersSetAsync() { await ... }

OnAfterRender
Les méthodes OnAfterRender et OnAfterRenderAsync sont appelées une fois que le rendu
d’un composant est terminé. Les références d’élément et de composant sont remplies à
ce stade (plus d’informations sur ces concepts ci-dessous). L’interactivité avec le
navigateur est activée à ce stade. Les interactions avec le DOM et l’exécution JavaScript
peuvent se produire en toute sécurité.

C#
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
...
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await ...
}
}

OnAfterRender et OnAfterRenderAsync ne sont pas appelés lors du prérendu sur le serveur.

Le paramètre firstRender est true la première fois que le composant est rendu ; sinon,
sa valeur est false .

IDisposable
Les composants Razor peuvent implémenter IDisposable pour supprimer des
ressources lorsque le composant est supprimé de l’interface utilisateur. Un composant
Razor peut implémenter IDispose à l’aide de la directive @implements :

razor

@using System
@implements IDisposable

...

@code {
public void Dispose()
{
...
}
}

Capturer des références de composant


Dans ASP.NET Web Forms, il est courant de manipuler une instance de contrôle
directement dans le code en faisant référence à son ID. Dans Blazor, il est également
possible de capturer et de manipuler une référence à un composant, bien que cela soit
beaucoup moins courant.

Pour capturer une référence de composant dans Blazor, utilisez l’attribut de directive
@ref . La valeur de l’attribut doit correspondre au nom d’un champ réglable avec le
même type que le composant référencé.

razor

<MyLoginDialog @ref="loginDialog" ... />

@code {
MyLoginDialog loginDialog = default!;

void OnSomething()
{
loginDialog.Show();
}
}

Lors du rendu du composant parent, le champ est rempli avec l’instance du composant
enfant. Vous pouvez ensuite appeler des méthodes sur l’instance du composant ou la
manipuler autrement.

La manipulation de l’état du composant directement à l’aide de références de


composants n’est pas recommandée. Cela empêche le rendu automatique du
composant aux moments appropriés.

Capturer des références d’éléments


Les composants Razor peuvent capturer des références à un élément. Contrairement aux
contrôles serveur HTML dans ASP.NET Web Forms, vous ne pouvez pas manipuler le
DOM directement à l’aide d’une référence d’élément dans Blazor. Blazor gère la plupart
des interactions DOM pour vous à l’aide de son algorithme différentiel DOM. Les
références d’élément capturées dans Blazor sont opaques. Toutefois, elles sont utilisées
pour passer une référence d’élément spécifique dans un appel d’interopérabilité
JavaScript. Pour plus d’informations sur l’interopérabilité JavaScript, consultez
Interopérabilité entre ASP.NET Core Blazor et JavaScript.

Composants basés sur un modèle


Dans ASP.NET Web Forms, vous pouvez créer des contrôles basés sur un modèle. Les
contrôles basés sur un modèle permettent au développeur de spécifier une partie du
code HTML utilisée pour rendre un contrôle de conteneur. Les mécanismes de création
de contrôles serveur avec modèles sont complexes, mais ils permettent des scénarios
puissants pour le rendu des données d’une manière personnalisable par l’utilisateur.
Parmi les exemples de contrôles modèles, citons Repeater et DataList .

Les composants Razor peuvent également être utilisés comme modèles en définissant
des paramètres de composant de type RenderFragment ou RenderFragment<T> . Un
RenderFragment représente un bloc de balisage Razor qui peut ensuite être rendu par le
composant. Un RenderFragment<T> est un bloc de balisage Razor qui prend un
paramètre qui peut être spécifié lorsque le fragment de rendu est rendu.

Contenu enfant
Les composants Razor peuvent capturer leur contenu enfant en tant que
RenderFragment et afficher ce contenu dans le cadre du rendu du composant. Pour
capturer le contenu enfant, définissez un paramètre de composant de type
RenderFragment et nommez-le ChildContent .

ChildContentComponent.razor

razor

<h1>Component with child content</h1>

<div>@ChildContent</div>

@code {
[Parameter]
public RenderFragment ChildContent { get; set; }
}

Un composant parent peut ensuite fournir du contenu enfant à l’aide de la syntaxe


Razor normale.

razor

<ChildContentComponent>
<ChildContent>
<p>The time is @DateTime.Now</p>
</ChildContent>
</ChildContentComponent>

Paramètres de modèle
Un composant Razor basé sur un modèle peut également définir plusieurs paramètres
de composant de type RenderFragment ou RenderFragment<T> . Le paramètre d’un
RenderFragment<T> peut être spécifié lorsqu’il est appelé. Pour spécifier un paramètre de

type générique pour un composant, utilisez la directive Razor @typeparam .

SimpleListView.razor

razor

@typeparam TItem

@Heading

<ul>
@foreach (var item in Items)
{
<li>@ItemTemplate(item)</li>
}
</ul>

@code {
[Parameter]
public RenderFragment Heading { get; set; }

[Parameter]
public RenderFragment<TItem> ItemTemplate { get; set; }

[Parameter]
public IEnumerable<TItem> Items { get; set; }
}

Lorsque vous utilisez un composant modèle, les paramètres de modèle peuvent être
spécifiés à l’aide d’éléments enfants qui correspondent aux noms des paramètres. Les
arguments de composant de type RenderFragment<T> transmis en tant qu’éléments ont
un paramètre implicite nommé context . Vous pouvez modifier le nom de ce paramètre
d’implémentation à l’aide de l’attribut Context sur l’élément enfant. Tous les paramètres
de type générique peuvent être spécifiés à l’aide d’un attribut qui correspond au nom
du paramètre de type. Le paramètre de type est déduit si possible :

razor

<SimpleListView Items="messages" TItem="string">


<Heading>
<h1>My list</h1>
</Heading>
<ItemTemplate Context="message">
<p>The message is: @message</p>
</ItemTemplate>
</SimpleListView>

La sortie de ce composant ressemble à ceci :

HTML

<h1>My list</h1>
<ul>
<li><p>The message is: message1</p></li>
<li><p>The message is: message2</p></li>
<ul>

Code-behind
Un composant Razor est généralement créé dans un fichier .razor unique. Toutefois, il
est également possible de séparer le code et le balisage à l’aide d’un fichier code-
behind. Pour utiliser un fichier de composant, ajoutez un fichier C# qui correspond au
nom de fichier du composant, mais avec une extension .cs ajoutée (Counter.razor.cs).
Utilisez le fichier C# pour définir une classe de base pour le composant. Vous pouvez
nommer la classe de base comme vous le souhaitez, mais il est courant de nommer la
classe de façon semblable à la classe de composant, avec une extension Base ajoutée
( CounterBase ). La classe basée sur le composant doit également dériver de
ComponentBase . Ensuite, dans le fichier de composant Razor, ajoutez la directive
@inherits pour spécifier la classe de base du composant ( @inherits CounterBase ).

Counter.razor

razor

@inherits CounterBase

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button @onclick="IncrementCount">Click me</button>

Counter.razor.cs

C#

public class CounterBase : ComponentBase


{
protected int currentCount = 0;
protected void IncrementCount()
{
currentCount++;
}
}

La visibilité des membres du composant dans la classe de base doit être protected ou
public pour être visible par la classe de composant.

Ressources supplémentaires
Ce qui précède n’est pas un traitement exhaustif de tous les aspects des composants
Razor. Pour plus d’informations sur la façon de Créer et utiliser des composants Razor
ASP.NET Core, consultez la documentation Blazor.

Précédent Suivant
Pages, routage et dispositions
Article • 08/06/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor pour les développeurs ASP
NET Web Forms pour Azure, disponible dans la documentation .NET ou au format
PDF à télécharger gratuitement pour le lire hors connexion.

Télécharger le PDF

Les applications ASP.NET Web Forms sont composées de pages définies dans les fichiers
.aspx. L’adresse de chaque page est basée sur son chemin d’accès de fichier physique
dans le projet. Lorsqu’un navigateur envoie une requête à la page, le contenu de la page
est rendu dynamiquement sur le serveur. Le rendu tient compte à la fois du balisage
HTML de la page et des contrôles du serveur.

Dans Blazor, chaque page de l’application est un composant, généralement défini dans
un fichier .razor, avec un ou plusieurs itinéraires spécifiés. Le routage se produit
principalement côté client sans impliquer une demande de serveur spécifique. Le
navigateur effectue d’abord une requête à l’adresse racine de l’application. Un
composant Router racine dans l’application Blazor gère ensuite l’interception des
demandes de navigation et les transfère au composant approprié.

Blazor prend également en charge le lien profond. Le lien profond se produit lorsque le
navigateur envoie une requête à un itinéraire spécifique autre que la racine de
l’application. Les demandes de liens profonds envoyés au serveur sont acheminées vers
l’application Blazor, qui achemine ensuite la requête côté client vers le composant
approprié.

Une page simple dans ASP.NET Web Forms peut contenir le balisage suivant :

Name.aspx
ASP.NET (C#)

<%@ Page Title="Name" Language="C#" MasterPageFile="~/Site.Master"


AutoEventWireup="true" CodeBehind="Name.aspx.cs"
Inherits="WebApplication1.Name" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent"


runat="server">
<div>
What is your name?<br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Submit"
OnClick="Button1_Click" />
</div>
<div>
<asp:Literal ID="Literal1" runat="server" />
</div>
</asp:Content>

Name.aspx.cs

C#

public partial class Name : System.Web.UI.Page


{
protected void Button1_Click1(object sender, EventArgs e)
{
Literal1.Text = "Hello " + TextBox1.Text;
}
}

La page équivalente d’une application Blazor se présente comme suit :

Name.razor

razor

@page "/Name"
@layout MainLayout

<div>
What is your name?<br />
<input @bind="text" />
<button @onclick="OnClick">Submit</button>
</div>
<div>
@if (name != null)
{
@:Hello @name
}
</div>
@code {
string text;
string name;

void OnClick() {
name = text;
}
}

Créer des pages


Pour créer une page dans Blazor, créez un composant et ajoutez la directive Razor
@page pour spécifier l’itinéraire du composant. La directive @page prend un seul

paramètre, qui est le modèle de routage à ajouter à ce composant.

razor

@page "/counter"

Le paramètre de modèle d’itinéraire est requis. Contrairement à ASP.NET Web Forms,


l’itinéraire vers un composant Blazorn’est pas déduit de son emplacement de fichier
(bien qu’il puisse s’agir d’une fonctionnalité ajoutée ultérieurement).

La syntaxe du modèle de routage est la même syntaxe de base que celle utilisée pour le
routage dans ASP.NET Web Forms. Les paramètres de routage sont spécifiés dans le
modèle à l’aide d’accolades. Blazor lie les valeurs de routage aux paramètres de
composant portant le même nom (sans respect de la casse).

razor

@page "/product/{id}"

<h1>Product @Id</h1>

@code {
[Parameter]
public string Id { get; set; }
}

Vous pouvez également spécifier des contraintes sur la valeur du paramètre de routage.
Par exemple, pour limiter l’ID produit à un int :

razor
@page "/product/{id:int}"

<h1>Product @Id</h1>

@code {
[Parameter]
public int Id { get; set; }
}

Pour obtenir la liste complète des contraintes d’itinéraire prises en charge par Blazor,
consultez Contraintes de routage.

Composant routeur
Le routage dans Blazor est géré par le composant Router . Le composant Router est
généralement utilisé dans le composant racine de l’application (App.razor).

razor

<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData"
DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>

Le composant Router découvre les composants routables dans les AppAssembly


spécifiés et dans le AdditionalAssemblies facultatif spécifié. Lorsque le navigateur
navigue, le Router intercepte la navigation et restitue le contenu de son paramètre
Found avec le RouteData extrait si une route correspond à l’adresse, sinon le Router

retourne son paramètre NotFound .

Le composant RouteView gère le rendu du composant correspondant spécifié par le


RouteData avec son layout s’il en a un. Si le composant correspondant n’a pas de

disposition, le paramètre facultatif spécifié DefaultLayout est utilisé.

Le composant LayoutView restitue son contenu enfant dans la disposition spécifiée.


Nous allons examiner les dispositions plus en détail plus loin dans ce chapitre.
Navigation
Dans ASP.NET Web Forms, vous déclenchez la navigation vers une autre page en
retournant une réponse de redirection au navigateur. Par exemple :

C#

protected void NavigateButton_Click(object sender, EventArgs e)


{
Response.Redirect("Counter");
}

Le retour d’une réponse de redirection n’est généralement pas possible dans Blazor.
Blazor n’utilise pas de modèle de demande-réponse. Toutefois, vous pouvez déclencher
des navigations de navigateur directement, comme vous le pouvez avec JavaScript.

Blazor fournit un service NavigationManager qui peut être utilisé pour :

Obtenir l’adresse actuelle du navigateur


Obtenir l’adresse de base
Déclencher des navigations
Recevoir une notification lorsque l’adresse change

Pour accéder à une autre adresse, utilisez la méthode NavigateTo :

razor

@page "/"
@inject NavigationManager NavigationManager

<button @onclick="Navigate">Navigate</button>

@code {
void Navigate() {
NavigationManager.NavigateTo("counter");
}
}

Pour obtenir une description de tous les membres NavigationManager , consultez URI et
assistance à l’état de navigation.

URL de base
Si votre application Blazor est déployée sous un chemin d’accès de base, vous devez
spécifier l’URL de base dans les métadonnées de la page à l’aide de la balise <base>
pour le routage vers la propriété de travail. Si la page hôte de l’application est rendue
par le serveur à l’aide de Razor, vous pouvez utiliser la syntaxe ~/ pour spécifier
l’adresse de base de l’application. Si la page hôte est HTML statique, vous devez
spécifier explicitement l’URL de base.

HTML

<base href="~/" />

Mise en page
La mise en page dans ASP.NET Web Forms est gérée par les pages maîtres. Les pages
maîtres définissent un modèle avec un ou plusieurs espaces réservés de contenu qui
peuvent ensuite être fournis par des pages individuelles. Les pages maîtres sont définies
dans les fichiers .master et commencent par la directive <%@ Master %> . Le contenu des
fichiers .master est codé comme vous le feriez pour une page .aspx , mais avec l’ajout de
contrôles <asp:ContentPlaceHolder> pour marquer où les pages peuvent fournir du
contenu.

Site.master

ASP.NET (C#)

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs"


Inherits="WebApplication1.SiteMaster" %>

<!DOCTYPE html>
<html lang="en">
<head runat="server">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%: Page.Title %> - My ASP.NET Application</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
</head>
<body>
<form runat="server">
<div class="container body-content">
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
<hr />
<footer>
<p>&copy; <%: DateTime.Now.Year %> - My ASP.NET
Application</p>
</footer>
</div>
</form>
</body>
</html>

Dans Blazor, vous gérez la mise en page à l’aide de composants de mise en page. Les
composants de disposition héritent de LayoutComponentBase , qui définit une propriété
unique Body de type RenderFragment , qui peut être utilisée pour restituer le contenu de
la page.

MainLayout.razor

razor

@inherits LayoutComponentBase
<h1>Main layout</h1>
<div>
@Body
</div>

Lorsque la page avec une mise en page est affichée, la page est rendue dans le contenu
de la disposition spécifiée à l’emplacement où la disposition affiche sa propriété Body .

Pour appliquer une mise en page à une page, utilisez la directive @layout :

razor

@layout MainLayout

Vous pouvez spécifier la disposition de tous les composants d’un dossier et de sous-
dossiers à l’aide d’un fichier _Imports.razor. Vous pouvez également spécifier un layout
par défaut pour toutes vos pages à l’aide du Composant routeur.

Les pages maîtres peuvent définir plusieurs espaces réservés de contenu, mais les
layouts dans Blazor n’ont qu’une seule propriété Body . Cette limitation des composants
de layout Blazor sera traitée dans une prochaine version.

Les pages maîtres dans ASP.NET Web Forms peuvent être imbriquées. Autrement dit,
une page maître peut également utiliser une page maître. Les composants de layout
dans Blazor peuvent également être imbriqués. Vous pouvez appliquer un composant
de layout à un composant de layout. Le contenu du layout interne sera affiché dans le
layout externe.

ChildLayout.razor

razor
@layout MainLayout
<h2>Child layout</h2>
<div>
@Body
</div>

Index.razor

razor

@page "/"
@layout ChildLayout
<p>I'm in a nested layout!</p>

La sortie rendue pour la page serait alors :

HTML

<h1>Main layout</h1>
<div>
<h2>Child layout</h2>
<div>
<p>I'm in a nested layout!</p>
</div>
</div>

Les mises en page dans Blazor ne définissent généralement pas les éléments HTML
racines d’une page ( <html> , <body> , <head> , etc.). Les éléments HTML racine sont plutôt
définis dans la page hôte d’une application Blazor, qui est utilisée pour afficher le
contenu HTML initial de l’application (voir Bootstrap Blazor). La page hôte peut afficher
plusieurs composants racines pour l’application avec le balisage environnant.

Les composants dans Blazor, y compris les pages, ne peuvent pas afficher de balises
<script> . Cette restriction de rendu existe, car les balises <script> sont chargées une

seule fois, puis ne peuvent pas être modifiées. Un comportement inattendu peut se
produire si vous essayez de restituer dynamiquement les balises à l’aide de la syntaxe
Razor. Au lieu de cela, toutes les balises <script> doivent être ajoutées à la page hôte
de l’application.

Précédent Suivant
Gestion de l'état
Article • 09/05/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor for ASP NET Web Forms
Developers for Azure (Blazor pour les développeurs ASP NET Web Forms pour
Azure), disponible sur la documentation .NET ou en tant que PDF téléchargeable
gratuitement qui peut être lu hors connexion.

Télécharger le PDF

La gestion de l’état est un concept clé d’applications Web Forms, facilitée par les
fonctionnalités ViewState, État de session, État de l’application et Postback. Ces
fonctionnalités avec état de l’infrastructure ont permis de masquer la gestion de l’état
requise pour une application et de permettre aux développeurs d’applications de se
concentrer sur les fonctionnalités à fournir. Avec ASP.NET Core et Blazor, certaines de
ces fonctionnalités ont été déplacées et certaines ont été complètement supprimées. Ce
chapitre explique comment maintenir l’état et fournir les mêmes fonctionnalités avec les
nouvelles fonctionnalités de Blazor.

Gestion de l’état de requête avec ViewState


Lorsque vous discutez de la gestion de l’état dans l’application Web Forms, de
nombreux développeurs pensent immédiatement à ViewState. Dans Web Forms,
ViewState gère l’état du contenu entre les requêtes HTTP en envoyant un bloc de texte
encodé volumineux vers le navigateur. Le champ ViewState peut être submergé par le
contenu d’une page contenant de nombreux éléments, pouvant s’étendre à plusieurs
mégaoctets de taille.

Avec Blazor Server, l’application conserve une connexion continue avec le serveur. L’état
de l’application, appelé circuit, est conservé dans la mémoire du serveur pendant que la
connexion est considérée comme active. L’état est supprimé uniquement lorsque
l’utilisateur quitte l’application ou une page particulière de l’application. Tous les
membres des composants actifs sont disponibles entre les interactions avec le serveur.

Cette fonctionnalité présente plusieurs avantages :

L’état du composant est facilement disponible et n’est pas reconstruit entre les
interactions.
L’état n’est pas transmis au navigateur.

Toutefois, il existe certains inconvénients pour la persistance de l’état des composants


en mémoire à prendre en compte :

Si le serveur redémarre entre la requête, l’état est perdu.


Votre solution d’équilibrage de charge de serveur web d’application doit inclure
des sessions épinglées pour vous assurer que toutes les requêtes du même
navigateur retournent au même serveur. Si une demande est envoyée à un autre
serveur, l’état est perdu.
La persistance de l’état du composant sur le serveur peut entraîner une sollicitation
de la mémoire sur le serveur web.

Pour les raisons précédentes, ne vous fiez pas uniquement à l’état du composant à
résider en mémoire sur le serveur. Votre application doit également inclure un magasin
de données de stockage pour les données entre les requêtes. Voici quelques exemples
simples de cette stratégie :

Dans une application de panier d’achat, conservez le contenu des nouveaux


éléments ajoutés au panier dans un enregistrement de base de données. Si l’état
sur le serveur est perdu, vous pouvez le rétablir à partir des enregistrements de
base de données.
Dans un formulaire web à plusieurs parties, vos utilisateurs s’attendent à ce que
votre application mémorise les valeurs entre chaque requête. Écrivez les données
entre chacune des publications de votre utilisateur dans un magasin de données
afin qu’elles puissent être extraites et assemblées dans la structure de réponse de
formulaire finale lorsque le formulaire à plusieurs parties est terminé.

Pour plus d’informations sur la gestion de l’état dans les applications Blazor, consultez
Gestion d’état ASP.NET Core Blazor.

Maintenir l’état avec session


Les développeurs Web Forms peuvent conserver des informations sur l’utilisateur
agissant actuellement avec l’objet de dictionnaire Microsoft.AspNetCore.Http.ISession. Il
est assez facile d’ajouter un objet avec une clé de chaîne à Session , et cet objet sera
disponible ultérieurement pendant les interactions de l’utilisateur avec l’application.
Dans une tentative d’élimination de la gestion de l’interaction avec HTTP, l’objet
Session a facilité la maintenance de l’état.

La signature de l’objet .NET Framework Session n’est pas identique à l’objet ASP.NET
Core Session . Envisagez la documentation relative à la nouvelle session ASP.NET Core
avant de décider de migrer et d’utiliser la nouvelle fonctionnalité d’état de session.

La session est disponible dans ASP.NET Core et Blazor Server, mais il est déconseillé de
l’utiliser en faveur du stockage des données dans un référentiel de données de manière
appropriée. L’état de session n’est pas non plus fonctionnel si les visiteurs refusent
l’utilisation des cookies HTTP dans votre application en raison de problèmes de
confidentialité.

La configuration d’ASP.NET Core et l’état de session est disponible dans l’article Session
et gestion de l’état dans ASP.NET Core.

État de l’application
L’objet Application dans l’infrastructure Web Forms fournit un référentiel de requêtes
croisées massif pour interagir avec la configuration et l’état de toute l’application. L’état
de l’application était un emplacement idéal pour stocker différentes propriétés de
configuration d’application qui seraient référencées par toutes les requêtes, quel que
soit l’utilisateur qui effectue la requête. Le problème avec l’objet Application était que
les données n’étaient pas conservées sur plusieurs serveurs. L’état de l’objet
d’application a été perdu entre les redémarrages.

Comme avec Session , il est recommandé que les données se déplacent vers un magasin
de stockage persistant accessible par plusieurs instances de serveur. S’il existe des
données volatiles auxquelles vous souhaitez accéder entre les requêtes et les
utilisateurs, vous pouvez facilement les stocker dans un service singleton qui peut être
injecté dans des composants qui nécessitent ces informations ou interactions.

La construction d’un objet pour maintenir l’état de l’application et sa consommation


peut ressembler à l’implémentation suivante :

C#

public class MyApplicationState


{
public int VisitorCounter { get; private set; } = 0;
public void IncrementCounter() => VisitorCounter += 1;
}

C#

app.AddSingleton<MyApplicationState>();

razor

@inject MyApplicationState AppState

<label>Total Visitors: @AppState.VisitorCounter</label>

L’objet MyApplicationState est créé une seule fois sur le serveur, et la valeur
VisitorCounter est extraite et sortie dans l’étiquette du composant. La valeur
VisitorCounter doit être conservée et récupérée à partir d’un magasin de données de

stockage pour la durabilité et la scalabilité.

Dans le navigateur
Les données d’application peuvent également être stockées côté client sur l’appareil de
l’utilisateur afin qu’elles soient disponibles ultérieurement. Il existe deux fonctionnalités
de navigateur qui permettent la persistance des données dans différentes étendues du
navigateur de l’utilisateur :

localStorage – étendu à l’ensemble du navigateur de l’utilisateur. Si la page est

rechargée, le navigateur est fermé et rouvert, ou un autre onglet est ouvert avec la
même URL, puis le même localStorage est fourni par le navigateur
sessionStorage – étendu à l’onglet actuel du navigateur de l’utilisateur. Si l’onglet

est rechargé, l’état persiste. Toutefois, si l’utilisateur ouvre un autre onglet à votre
application ou ferme et ouvre à nouveau le navigateur, l’état est perdu.

Vous pouvez écrire du code JavaScript personnalisé pour interagir avec ces
fonctionnalités, ou il existe un certain nombre de packages NuGet que vous pouvez
utiliser pour fournir cette fonctionnalité. Un de ces packages est
Microsoft.AspNetCore.ProtectedBrowserStorage .

Pour obtenir des instructions sur l’utilisation de ce package pour interagir avec
localStorage et sessionStorage , consultez l’article Blazor State Management (Gestion
d’état Blazor).
Précédent Suivant
Formulaires et validation
Article • 08/06/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor pour les développeurs ASP
NET Web Forms pour Azure, disponible dans la documentation .NET ou au format
PDF à télécharger gratuitement pour le lire hors connexion.

Télécharger le PDF

Le framework ASP.NET Web Forms inclut un ensemble de contrôles de serveur de


validation qui gèrent la validation des entrées utilisateur saisies dans un formulaire
( RequiredFieldValidator , CompareValidator , RangeValidator , etc.). Le framework
ASP.NET Web Forms prend également en charge la liaison et la validation du modèle en
fonction d’annotations de données ( [Required] , [StringLength] , [Range] , etc.). La
logique de validation peut être appliquée à la fois sur le serveur et sur le client en
utilisant une validation discrète basée sur JavaScript. Le contrôle du serveur
ValidationSummary sert à présenter un résumé des erreurs de validation à l'utilisateur.

Blazor prend en charge le partage de la logique de validation entre le client et le


serveur. ASP.NET fournit des implémentations JavaScript prédéfinies de nombreuses
validations de serveur courantes. Dans de nombreux cas, le développeur doit toujours
écrire JavaScript pour implémenter entièrement sa logique de validation spécifique à
l’application. Les mêmes types de modèles, annotations de données et la même logique
de validation peuvent être utilisés sur le serveur et le client.

Blazor fournit un ensemble de composants d’entrée. Les composants d’entrée gèrent les
données de champ de liaison à un modèle et valident l’entrée utilisateur lorsque le
formulaire est envoyé.

Composant d’entrée Élément HTML rendu


Composant d’entrée Élément HTML rendu

InputCheckbox <input type="checkbox">

InputDate <input type="date">

InputNumber <input type="number">

InputSelect <select>

InputText <input>

InputTextArea <textarea>

Le composant EditForm encapsule ces composants d'entrée et orchestre le processus


de validation via un EditContext . Lors de la création d’un EditForm , vous spécifiez
l’instance de modèle à lier à l’aide du paramètre Model . La validation est généralement
effectuée à l’aide d’annotations de données, et elle est extensible. Pour activer la
validation basée sur des annotations de données, ajoutez le composant
DataAnnotationsValidator en tant qu’enfant de EditForm . Le composant EditForm
fournit un événement pratique pour gérer les soumissions valides ( OnValidSubmit ) et
non valides ( OnInvalidSubmit ). Il existe également un événement plus générique
OnSubmit qui vous permet de déclencher et de gérer la validation vous-même.

Pour afficher un résumé des erreurs de validation, utilisez le composant


ValidationSummary . Pour afficher des messages de validation pour un champ de saisie
spécifique, utilisez le composant ValidationMessage , en spécifiant une expression
lambda pour le paramètre For qui pointe vers le membre de modèle approprié.

Le type de modèle suivant définit plusieurs règles de validation à l’aide d’annotations de


données :

C#

using System;
using System.ComponentModel.DataAnnotations;

public class Starship


{
[Required]
[StringLength(16,
ErrorMessage = "Identifier too long (16 character limit).")]
public string Identifier { get; set; }

public string Description { get; set; }

[Required]
public string Classification { get; set; }

[Range(1, 100000,
ErrorMessage = "Accommodation invalid (1-100000).")]
public int MaximumAccommodation { get; set; }

[Required]
[Range(typeof(bool), "true", "true",
ErrorMessage = "This form disallows unapproved ships.")]
public bool IsValidatedDesign { get; set; }

[Required]
public DateTime ProductionDate { get; set; }
}

Le composant suivant illustre la création d’un formulaire dans Blazor, basé sur le type de
modèle Starship :

razor

<h1>New Ship Entry Form</h1>

<EditForm Model="@starship" OnValidSubmit="@HandleValidSubmit">


<DataAnnotationsValidator />
<ValidationSummary />

<p>
<label for="identifier">Identifier: </label>
<InputText id="identifier" @bind-Value="starship.Identifier" />
<ValidationMessage For="() => starship.Identifier" />
</p>
<p>
<label for="description">Description (optional): </label>
<InputTextArea id="description" @bind-Value="starship.Description"
/>
</p>
<p>
<label for="classification">Primary Classification: </label>
<InputSelect id="classification" @bind-
Value="starship.Classification">
<option value="">Select classification ...</option>
<option value="Exploration">Exploration</option>
<option value="Diplomacy">Diplomacy</option>
<option value="Defense">Defense</option>
</InputSelect>
<ValidationMessage For="() => starship.Classification" />
</p>
<p>
<label for="accommodation">Maximum Accommodation: </label>
<InputNumber id="accommodation" @bind-
Value="starship.MaximumAccommodation" />
<ValidationMessage For="() => starship.MaximumAccommodation" />
</p>
<p>
<label for="valid">Engineering Approval: </label>
<InputCheckbox id="valid" @bind-Value="starship.IsValidatedDesign"
/>
<ValidationMessage For="() => starship.IsValidatedDesign" />
</p>
<p>
<label for="productionDate">Production Date: </label>
<InputDate id="productionDate" @bind-Value="starship.ProductionDate"
/>
<ValidationMessage For="() => starship.ProductionDate" />
</p>

<button type="submit">Submit</button>
</EditForm>

@code {
private Starship starship = new Starship();

private void HandleValidSubmit()


{
// Save the data
}
}

Après l’envoi du formulaire, les données liées au modèle n’ont pas été enregistrées dans
un magasin de données, par exemple une base de données. Dans une application Blazor
WebAssembly, les données doivent être envoyées au serveur. Par exemple, à l’aide d’une
requête HTTP POST. Dans une application serveur Blazor, les données sont déjà sur le
serveur, mais elles doivent être conservées. La gestion de l'accès aux données dans les
applications Blazor est abordée dans la section Traitement des données.

Ressources supplémentaires
Pour plus d’informations sur les formulaires et la validation dans les applications Blazor,
consultez la documentation Blazor.

Précédent Suivant
Utilisation des données
Article • 08/06/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor pour les développeurs ASP
NET Web Forms pour Azure, disponible dans la documentation .NET ou au format
PDF à télécharger gratuitement pour le lire hors connexion.

Télécharger le PDF

L’accès aux données est l’épine dorsale d’une application ASP.NET Web Forms. Si vous
créez des formulaires pour le web, qu’advient-il de ces données ? Avec Web Forms, il
existe plusieurs techniques d’accès aux données que vous pouvez utiliser pour interagir
avec une base de données :

Data Sources
ADO.NET
Entity Framework

Les sources de données étaient des contrôles que vous pouviez placer sur une page
Web Forms et configurer comme d’autres contrôles. Visual Studio fournissait un
ensemble convivial de boîtes de dialogue pour configurer et lier les contrôles à vos
pages Web Forms. Les développeurs qui apprécient une approche « low code » ou « no
code » préféraient cette technique lorsque Web Forms a été publié pour la première
fois.
ADO.NET est l’approche de bas niveau pour interagir avec une base de données. Vos
applications pouvaient créer une connexion à la base de données avec des commandes,
des tables de données et des jeux de données à des fins d’interaction. Les résultats
pouvaient ensuite être liés aux champs à l’écran avec peu de code. L’inconvénient de
cette approche était que chaque ensemble d’objets ADO.NET ( Connection , Command et
DataTable ) était lié aux bibliothèques fournies par un fournisseur de base de données.
L’utilisation de ces composants rendait le code rigide et difficile à migrer vers une autre
base de données.

Entity Framework
Entity Framework (EF) est le framework open source de mappage objet-relationnel géré
par .NET Foundation. Initialement publié avec .NET Framework, EF permet de générer du
code pour les connexions de base de données, les schémas de stockage et les
interactions. Avec cette abstraction, vous pouvez vous concentrer sur les règles métier
de votre application et autoriser la gestion de la base de données par un administrateur
de base de données approuvé. Dans .NET, vous pouvez utiliser une version mise à jour
d’EF appelée EF Core. EF Core permet de générer et de gérer les interactions entre votre
code et la base de données avec une série de commandes disponibles pour vous à l’aide
de l’outil en ligne de commande dotnet ef . Examinons quelques exemples pour vous
aider à utiliser une base de données.

EF Code First
Un moyen rapide de commencer à créer vos interactions de base de données consiste à
commencer par les objets de classe que vous souhaitez utiliser. EF fournit un outil
permettant de générer le code de base de données approprié pour vos classes. Cette
approche est appelée développement « Code First ». Considérez la classe Product
suivante pour un exemple d’application de vitrine que nous voulons stocker dans une
base de données relationnelle comme Microsoft SQL Server.
C#

public class Product


{
public int Id { get; set; }

[Required]
public string Name { get; set; }

[MaxLength(4000)]
public string Description { get; set; }

[Range(0, 99999,99)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }
}

Le produit a une clé primaire et trois champs supplémentaires qui seraient créés dans
notre base de données :

EF identifie la propriété Id comme clé primaire par convention.


Name est stocké dans une colonne configurée pour le stockage texte. L’attribut
[Required] décorant cette propriété ajoute une contrainte not null pour aider à

appliquer ce comportement déclaré de la propriété.


Description est stocké dans une colonne configurée pour le stockage texte et a

une longueur maximale configurée de 4 000 caractères, comme indiqué par


l’attribut [MaxLength] . Le schéma de base de données est configuré avec une
colonne nommée MaxLength à l’aide du type de données varchar(4000) .
La propriété Price est stockée en tant que devise. L’attribut [Range] génère des
contraintes appropriées pour empêcher le stockage de données en dehors des
valeurs minimales et maximales déclarées.

Nous devons ajouter cette classe Product à une classe de contexte de base de données
qui définit les opérations de connexion et de traduction avec notre base de données.

C#

public class MyDbContext : DbContext


{
public DbSet<Product> Products { get; set; }
}

La classe MyDbContext fournit la propriété qui définit l’accès et la traduction de la classe


Product . Votre application configure cette classe à des fins d’interaction avec la base de

données à l’aide des entrées suivantes dans la méthode ConfigureServices de la classe


Startup (ou emplacement approprié dans Program.cs à l’aide de la propriété

builder.Services au lieu de services ) :

C#

services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer("MY DATABASE CONNECTION STRING"));

Le code précédent se connecte à une base de données SQL Server avec la chaîne de
connexion spécifiée. Vous pouvez placer la chaîne de connexion dans votre fichier
appsettings.json, des variables d’environnement ou d’autres emplacements de stockage
de configuration et remplacer cette chaîne incorporée de manière appropriée.

Vous pouvez ensuite générer la table de base de données appropriée pour cette classe à
l’aide des commandes suivantes :

CLI .NET

dotnet ef migrations add 'Create Product table'


dotnet ef database update

La première commande définit les modifications que vous apportez au schéma de base
de données en tant que nouvelle migration EF appelée Create Product table . Une
migration définit comment appliquer et supprimer vos nouvelles modifications de base
de données.

Une fois eappliqué, vous disposez d’une table simple Product dans votre base de
données et de certaines nouvelles classes ajoutées au projet qui aident à gérer le
schéma de base de données. Vous pouvez trouver ces classes générées, par défaut, dans
un nouveau dossier appelé Migrations. Lorsque vous apportez des modifications à la
classe Product ou ajoutez des classes associées que vous souhaitez faire interagir avec
votre base de données, vous devez réexécuter les commandes en ligne de commande
avec un nouveau nom de migration. Cette commande génère un autre ensemble de
classes de migration pour mettre à jour votre schéma de base de données.

EF Database First
Pour les bases de données existantes, vous pouvez générer les classes pour EF Core à
l’aide des outils en ligne de commande .NET. Pour créer la structure des classes, utilisez
une variante de la commande suivante :

CLI .NET
dotnet ef dbcontext scaffold "CONNECTION STRING"
Microsoft.EntityFrameworkCore.SqlServer -c MyDbContext -t Product -t
Customer

La commande précédente se connecte à la base de données à l’aide de la chaîne de


connexion spécifiée et du fournisseur Microsoft.EntityFrameworkCore.SqlServer . Une
fois connectée, une classe de contexte de base de données nommée MyDbContext est
créée. En outre, les classes de prise en charge sont créées pour les tables Product et
Customer qui ont été spécifiées avec les options -t . Il existe de nombreuses options de

configuration pour cette commande afin de générer la hiérarchie de classes appropriée


pour votre base de données. Pour accéder à une référence complète, consultez la
documentation de la commande.

Pour plus d’informations sur EF Core, consultez le site Microsoft Docs.

Interagir avec les services web


Lorsque ASP.NET a été publiée pour la première fois, les services SOAP étaient le moyen
préféré pour les serveurs web et les clients d’échanger des données. Cela a changé et les
interactions préférées avec les services ont changé et il s’agit maintenant des
interactions clientes HTTP directes. Avec ASP.NET Core et Blazor, vous pouvez inscrire la
configuration de votre HttpClient dans Program.cs ou dans la méthode
ConfigureServices de la classe Startup . Utilisez cette configuration lorsque vous devez
interagir avec le point de terminaison HTTP. Tenez compte du code de configuration
suivant :

C#

// in Program.cs
builder.Services.AddHttpClient("github", client =>
{
client.BaseAddress = new Uri("http://api.github.com/");
// Github API versioning
client.DefaultRequestHeaders.Add("Accept",
"application/vnd.github.v3+json");
// Github requires a user-agent
client.DefaultRequestHeaders.Add("User-Agent", "BlazorWebForms-Sample");
});

Chaque fois que vous devez accéder aux données à partir de GitHub, créez un client
avec le nom github . Le client est configuré avec l’adresse de base et les en-têtes de
demande sont définis de manière appropriée. Injectez les éléments IHttpClientFactory
dans vos composants Blazor avec la directive @inject ou un attribut [Inject] sur une
propriété. Créez votre client nommé et interagissez avec les services à l’aide de la
syntaxe suivante :

razor

@inject IHttpClientFactory factory

...

@code {
protected override async Task OnInitializedAsync()
{
var client = factory.CreateClient("github");
var response = await client.GetAsync("repos/dotnet/docs/issues");
response.EnsureStatusCode();
var content = await response.Content.ReadAsStringAsync();
}
}

Cette méthode retourne la chaîne décrivant la collection de problèmes dans le dépôt


GitHub dotnet/docs. Elle retourne du contenu au format JSON et est désérialisée dans
les objets de problème GitHub appropriés. Il existe de nombreuses façons de configurer
le service HttpClientFactory pour fournir des objets préconfigurés HttpClient . Essayez
de configurer plusieurs instances HttpClient avec différents noms et points de
terminaison pour les différents services web que vous utilisez. Cette approche facilite
l’utilisation de vos interactions avec ces services sur chaque page. Pour plus
d’informations, consultez Effectuer des requêtes HTTP en utilisant IHttpClientFactory.

Précédent Suivant
Modules, gestionnaires et intergiciels
Article • 08/06/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor pour les développeurs ASP
NET Web Forms pour Azure, disponible dans la documentation .NET ou au format
PDF à télécharger gratuitement pour le lire hors connexion.

Télécharger le PDF

Une application ASP.NET Core repose sur une série d’intergiciels. L’intergiciel est
composé de gestionnaires organisés dans un pipeline pour gérer les requêtes et les
réponses. Dans une application Web Forms, les gestionnaires et modules HTTP résolvent
des problèmes similaires. Dans ASP.NET Core, les modules, les gestionnaires,
Global.asax.cs et le cycle de vie de l’application sont remplacés par des intergiciels. Dans
ce chapitre, vous allez découvrir les intergiciels dans le contexte d’une application
Blazor.

Vue d’ensemble
Le pipeline de requête ASP.NET Core est composé d’une séquence de délégués de
requête, appelés l’un après l’autre. Le diagramme suivant illustre le concept. Le thread
d’exécution suit les flèches noires.
Le diagramme précédent n’a pas de concept d’événements de cycle de vie. Ce concept
est fondamental pour la façon dont les requêtes ASP.NET Web Forms sont gérées. Ce
système facilite la raison du processus qui se produit et permet d’insérer des intergiciels
à tout moment. L’intergiciel s’exécute dans l’ordre dans lequel il est ajouté au pipeline
de requête. Il est également ajouté dans le code au lieu des fichiers de configuration,
généralement dans Startup.cs.

Katana
Les lecteurs familiarisés avec Katana se sentiront à l’aise dans ASP.NET Core. En fait,
Katana est un framework à partir duquel ASP.NET Core dérive. Il a introduit des modèles
d’intergiciels et de pipelines similaires pour ASP.NET 4.x. L’intergiciel conçu pour Katana
peut être adapté pour fonctionner avec le pipeline ASP.NET Core.

Intergiciels courants
ASP.NET 4.x inclut de nombreux modules. De la même manière, ASP.NET Core dispose
également de nombreux composants d’intergiciels. Les modules IIS peuvent être utilisés
dans certains cas avec ASP.NET Core. Dans d’autres cas, l’intergiciel ASP.NET Core natif
peut être disponible.

Le tableau suivant répertorie les intergiciels et les composants de remplacement dans


ASP.NET Core.
Module Module ASP.NET 4.x Option ASP.NET Core

Erreurs HTTP CustomErrorModule Middleware (intergiciel) de pages


de codes d’état

Document par défaut DefaultDocumentModule Middleware de fichiers par défaut

Exploration de répertoires DirectoryListingModule Middleware d’exploration des


répertoires

Compression dynamique DynamicCompressionModule Middleware de compression des


réponses

Suivi des demandes ayant FailedRequestsTracingModule Journalisation ASP.NET Core


échoué

Mise en cache des fichiers FileCacheModule Intergiciel de mise en cache des


réponses

Mise en cache HTTP HttpCacheModule Intergiciel de mise en cache des


réponses

Journalisation HTTP HttpLoggingModule Journalisation ASP.NET Core

Redirection HTTP HttpRedirectionModule Intergiciel de réécriture d’URL

Filtres ISAPI IsapiFilterModule Middleware

ISAPI IsapiModule Middleware

Filtrage des demandes RequestFilteringModule IRule Middleware de réécriture


d’URL

Réécriture d’URL† RewriteModule Intergiciel de réécriture d’URL

Compression statique StaticCompressionModule Middleware de compression des


réponses

Contenu statique StaticFileModule Middleware de fichiers statiques

Autorisation d’URL UrlAuthorizationModule Identité ASP.NET Core

Cette liste n’est pas exhaustive, mais devrait vous donner une idée des correspondances
qui existent entre les deux frameworks. Pour obtenir une liste plus détaillée, consultez
Modules IIS avec ASP.NET Core.

Intergiciels personnalisés
Un intergiciel intégré peut ne pas gérer tous les scénarios nécessaires pour une
application. Dans ce cas, il est logique de créer votre propre intergiciel. Il existe plusieurs
façons de définir l’intergiciel (middleware), le plus simple étant un délégué simple.
Examinez l’intergiciel (middleware) suivant, qui accepte une demande de culture d’une
chaîne de requête :

C#

public class Startup


{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
var cultureQuery = context.Request.Query["culture"];

if (!string.IsNullOrWhiteSpace(cultureQuery))
{
var culture = new CultureInfo(cultureQuery);

CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}

// Call the next delegate/middleware in the pipeline


await next();
});

app.Run(async (context) =>


await context.Response.WriteAsync(
$"Hello {CultureInfo.CurrentCulture.DisplayName}"));
}
}

Le middleware peut également être défini en tant que classe, soit en implémentant
l’interface IMiddleware , soit en suivant la convention d’intergiciel. Pour plus
d’informations, consultez Écrire un intergiciel ASP.NET Core personnalisé.

Précédent Suivant
la configuration d’une application ;
Article • 08/06/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor pour les développeurs ASP
NET Web Forms pour Azure, disponible dans la documentation .NET ou au format
PDF à télécharger gratuitement pour le lire hors connexion.

Télécharger le PDF

La principale façon de charger la configuration de l'application dans les formulaires web


consiste à utiliser des entrées dans le fichier web.config, soit sur le serveur, soit dans un
fichier de configuration connexe référencé par web.config. Vous pouvez utiliser l'objet
statique ConfigurationManager pour interagir avec les paramètres de l'application, les
chaînes de connexion du référentiel de données et d'autres fournisseurs de
configuration étendue qui sont ajoutés à l'application. Il est fréquent de voir des
interactions avec la configuration de l'application, notamment dans le code suivant :

C#

var configurationValue =
ConfigurationManager.AppSettings["ConfigurationSettingName"];
var connectionString =
ConfigurationManager.ConnectionStrings["MyDatabaseConnectionName"].Connectio
nString;

Avec ASP.NET Core et Blazor côté serveur, le fichier web.config peut être présent si votre
application est hébergée sur un serveur Windows IIS. Mais il n’existe aucune interaction
ConfigurationManager avec cette configuration et vous pouvez recevoir une

configuration d’application plus structurée à partir d’autres sources. Voyons comment la


configuration est collectée et comment il est possible de toujours accéder aux
informations de configuration à partir d’un fichier web.config.
Sources de configuration
ASP.NET Core reconnaît qu’il existe de nombreuses sources de configuration que vous
pouvez utiliser pour votre application. L’infrastructure tente de vous offrir les
fonctionnalités par défaut. La configuration est lue et agrégée à partir de ces différentes
sources par ASP.NET Core. Les valeurs chargées ultérieurement pour la même clé de
configuration sont prioritaires sur les valeurs antérieures.

ASP.NET Core a été conçu pour prendre en charge le cloud et faciliter la configuration
des applications pour les opérateurs et les développeurs. ASP.NET Core prend en
compte l’environnement et identifie s’il est en cours d’exécution dans votre
environnement Production ou Development . L’indicateur d’environnement est défini
dans la variable d’environnement système ASPNETCORE_ENVIRONMENT . Si aucune valeur
n’est configurée, l’application s’exécute par défaut dans l’environnement Production .

Votre application peut déclencher et ajouter une configuration à partir de plusieurs


sources en fonction du nom de l’environnement. Par défaut, la configuration est chargée
à partir des ressources suivantes dans l’ordre indiqué :

1. Fichier appsettings.json, s’il est présent


2. Fichier appsettings.{ENVIRONMENT_NAME}.json, s’il est présent
3. Fichier de secrets utilisateur sur le disque, s’il est présent
4. Variables d'environnement
5. Arguments de ligne de commande

Format du fichier appsettings.json et accès à


celui-ci
Le fichier appsettings.json peut être hiérarchique, avec des valeurs structurées comme
l’exemple JSON suivant :

JSON

{
"section0": {
"key0": "value",
"key1": "value"
},
"section1": {
"key0": "value",
"key1": "value"
}
}
Lorsqu’il est présenté avec le modèle JSON précédent, le système de configuration
aplatit les valeurs enfants et référence leurs chemins hiérarchiques complets. Un
caractère deux-points ( : ) sépare chaque propriété de la hiérarchie. Par exemple, la clé
configuration section1:key0 permet d’accéder à la valeur du section1 littéral de
l’objet key0 .

Secrets utilisateur
Les secrets utilisateur sont les suivants :

Valeurs de configuration stockées dans un fichier JSON sur la station de travail du


développeur, en dehors du dossier de développement de l’application.
Chargé uniquement lors de l’exécution dans l’environnement Development .
Associé à une application spécifique.
Géré avec la commande user-secrets de l’interface CLI .NET.

Configurez votre application pour le stockage des secrets en exécutant la commande


user-secrets :

CLI .NET

dotnet user-secrets init

La commande précédente ajoute un élément UserSecretsId au fichier projet. L’élément


contient un GUID, utilisé pour associer des secrets à l’application. Vous pouvez ensuite
définir un secret avec la commande set . Par exemple :

CLI .NET

dotnet user-secrets set "Parent:ApiKey" "12345"

La commande précédente met à disposition la clé de configuration sur la station de


travail Parent:ApiKey d’un développeur avec la valeur 12345 .

Pour plus d’informations sur la création, le stockage et la gestion des secrets utilisateur,
consultez le document Stockage sécurisé des secrets d’application en développement
dans ASP.NET Core.

Variables d'environnement
L’ensemble suivant de valeurs chargées dans la configuration de votre application
représente les variables d’environnement du système. Tous les paramètres de variable
d’environnement de votre système sont désormais accessibles via l’API de configuration.
Les valeurs hiérarchiques sont aplaties et séparées par un caractère deux-points lors de
la lecture depuis votre application. Toutefois, certains systèmes d’exploitation
n’autorisent pas les noms de variables d’environnement contenant le caractère deux-
points. ASP.NET Core résout cette limitation en convertissant les valeurs comportant des
traits de soulignement doubles ( __ ) en deux-points lorsqu’elles sont accessibles. La
valeur Parent:ApiKey de la section des secrets d'utilisateur ci-dessus peut être
remplacée par la variable d'environnement Parent__ApiKey .

Arguments de ligne de commande


La configuration peut également être fournie sous forme d'arguments de ligne de
commande lors du démarrage de votre application. Utilisez le double tiret ( -- ) ou la
barre oblique ( / ) pour indiquer le nom de la valeur de configuration à définir et la
valeur à configurer. La syntaxe ressemble aux commandes suivantes :

CLI .NET

dotnet run CommandLineKey1=value1 --CommandLineKey2=value2


/CommandLineKey3=value3
dotnet run --CommandLineKey1 value1 /CommandLineKey2 value2
dotnet run Parent:ApiKey=67890

Retour de web.config
Si vous avez déployé votre application pour Windows sur IIS, le fichier web.config
configure toujours IIS pour gérer votre application. Par défaut, IIS ajoute une référence
au module ASP.NET Core (ANCM). ANCM est un module IIS natif qui héberge votre
application à la place du serveur web Kestrel. Cette section web.config ressemble au
balisage XML suivant :

XML

<?xml version="1.0" encoding="utf-8"?>


<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*"
modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath=".\MyApp.exe"
stdoutLogEnabled="false"
stdoutLogFile=".\logs\stdout"
hostingModel="inprocess" />
</system.webServer>
</location>
</configuration>

La configuration spécifique à l'application peut être définie en imbriquant un élément


environmentVariables dans l'élément aspNetCore . Les valeurs définies dans cette section

sont présentées à l'application ASP.NET Core sous forme de variables d'environnement.


Les variables d'environnement se chargent de manière appropriée pendant ce segment
du démarrage de l'application.

XML

<aspNetCore processPath="dotnet"
arguments=".\MyApp.dll"
stdoutLogEnabled="false"
stdoutLogFile=".\logs\stdout"
hostingModel="inprocess">
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development"
/>
<environmentVariable name="Parent:ApiKey" value="67890" />
</environmentVariables>
</aspNetCore>

Lire la configuration dans l’application


ASP.NET Core permet de configurer les applications via l'interface IConfiguration. Cette
interface de configuration doit être sollicitée par vos composants Blazor, vos pages
Blazor et toute autre classe gérée par ASP.NET Core qui doit accéder à la configuration.
Le framework ASP.NET Core remplira automatiquement cette interface avec la
configuration résolue configurée précédemment. Sur une page Blazor ou un balisage
Razor d'un composant, vous pouvez injecter l'objet IConfiguration avec une directive
@inject en haut du fichier .razor, comme ceci :

razor

@inject IConfiguration Configuration

Cette déclaration précédente rend l'objet IConfiguration disponible comme variable


Configuration dans le reste du modèle Razor.
Les paramètres de configuration individuels peuvent être lus en spécifiant la hiérarchie
des paramètres de configuration recherchée comme paramètre d'indexation :

C#

var mySetting = Configuration["section1:key0"];

Vous pouvez récupérer des sections entières de configuration en utilisant la méthode


GetSection de récupération d'une collection de clés à un emplacement spécifique, avec
une syntaxe similaire à celle de GetSection("section1") afin de récupérer la
configuration pour la section1 de l'exemple précédent.

Configuration fortement typée


Avec Web Forms, il était possible de créer un type de configuration fortement typé qui
héritait du type ConfigurationSection et des types associés. Un type
ConfigurationSection vous permettait de configurer certaines règles de gestion et le

traitement de ces valeurs de configuration.

Dans ASP.NET Core, vous pouvez spécifier une hiérarchie de classes qui recevra les
valeurs de configuration. Ces classes :

Il n'est pas nécessaire d'hériter d'une classe parente.


Doit inclure des propriétés public qui correspondent aux propriétés et aux
références de type pour la structure de configuration que vous souhaitez capturer.

Pour l'exemple appsettings.json précédent, vous pourriez définir les classes suivantes
pour capturer les valeurs :

C#

public class MyConfig


{
public MyConfigSection section0 { get; set;}

public MyConfigSection section1 { get; set;}


}

public class MyConfigSection


{
public string key0 { get; set; }

public string key1 { get; set; }


}
Cette hiérarchie de classes peut être renseignée en ajoutant la ligne suivante à la
méthode Startup.ConfigureServices (ou à l'emplacement approprié dans le fichier
Program.cs en utilisant la propriété builder.Services au lieu de services ) :

C#

services.Configure<MyConfig>(Configuration);

Dans le reste de l'application, vous pouvez ajouter un paramètre d'entrée aux classes ou
une directive @inject dans les modèles Razor de type IOptions<MyConfig> pour recevoir
les paramètres de configuration fortement typés. La propriété IOptions<MyConfig>.Value
renverra la valeur MyConfig obtenue à partir des paramètres de configuration.

razor

@inject IOptions<MyConfig> options


@code {
var MyConfiguration = options.Value;
var theSetting = MyConfiguration.section1.key0;
}

Pour plus d’informations sur la fonctionnalité Options, consultez le document Modèle


d’options dans ASP.NET Core.

Précédent Suivant
Sécurité : Authentification et
autorisation dans ASP.NET Web Forms
et Blazor
Article • 08/06/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor pour les développeurs ASP
NET Web Forms pour Azure, disponible dans la documentation .NET ou au format
PDF à télécharger gratuitement pour le lire hors connexion.

Télécharger le PDF

La migration d’une application Web Forms ASP.NET vers Blazor nécessite très
probablement une mise à jour de la façon dont l’authentification et l’autorisation sont
effectuées, en supposant que l’application avait configuré l’authentification. Ce chapitre
explique comment migrer à partir du modèle de fournisseur universel ASP.NET Web
Forms (pour l’appartenance, les rôles et les profils utilisateur) et comment utiliser
ASP.NET Core Identity à partir d’applications Blazor. Bien que ce chapitre traite des
étapes et des considérations générales, les étapes détaillées et les scripts sont
disponibles dans la documentation référencée.

Fournisseurs universels ASP.NET


Depuis ASP.NET 2.0, la plateforme ASP.NET Web Forms a pris en charge un modèle
fournisseur pour diverses fonctionnalités, y compris l’appartenance. Le fournisseur
d’appartenance universel, ainsi que le fournisseur de rôles facultatif, est généralement
déployé avec des applications ASP.NET Web Forms. Il offre un moyen robuste et
sécurisé de gérer l’authentification et l’autorisation qui continue de fonctionner
correctement aujourd’hui. L’offre la plus récente de ces fournisseurs universels est
disponible en tant que package NuGet, Microsoft.AspNet.Providers .

Les fournisseurs universels fonctionnent avec un schéma de base de données SQL qui
inclut des tables telles que aspnet_Applications , aspnet_Membership , aspnet_Roles et
aspnet_Users . Lorsqu’il est configuré en exécutant la commande aspnet_regsql.exe, les

fournisseurs installent des tables et des procédures stockées qui fournissent toutes les
requêtes et commandes nécessaires pour fonctionner avec les données sous-jacentes.
Le schéma de base de données et ces procédures stockées ne sont pas compatibles
avec les systèmes ASP.NET Identity et ASP.NET Core Identity plus récents. Les données
existantes doivent donc être migrées vers le nouveau système. La figure 1 montre un
exemple de schéma de table configuré pour les fournisseurs universels.

Le fournisseur universel gère les utilisateurs, l’appartenance, les rôles et les profils. Les
utilisateurs reçoivent des identificateurs globaux uniques et des informations de base
telles que userId, userName, etc. sont stockées dans la table aspnet_Users . Les
informations d’authentification, telles que le mot de passe, le format de mot de passe, le
sel de mot de passe, les compteurs de verrouillage et les détails, etc. sont stockées dans
la table aspnet_Membership . Les rôles se composent simplement de noms et
d’identificateurs uniques, qui sont attribués aux utilisateurs via la table d’association
aspnet_UsersInRoles , fournissant une relation plusieurs-à-plusieurs.

Si votre système existant utilise des rôles en plus de l’appartenance, vous devez migrer
les comptes d’utilisateur, les mots de passe associés, les rôles et l’appartenance au rôle
dans ASP.NET Core Identity. Vous devrez également probablement mettre à jour votre
code où vous effectuez actuellement des vérifications de rôle à l’aide des instructions if
pour exploiter à la place des filtres déclaratifs, des attributs et/ou de l’assistance des
balises. Nous examinerons plus en détail les considérations relatives à la migration à la
fin de ce chapitre.

Configuration d’autorisation dans Web Forms


Pour configurer l’accès autorisé à certaines pages dans une application ASP.NET Web
Forms, vous spécifiez généralement que certaines pages ou dossiers sont inaccessibles
aux utilisateurs anonymes. Cette configuration est effectuée dans le fichier web.config :

XML

<?xml version="1.0"?>
<configuration>
<system.web>
<authentication mode="Forms">
<forms defaultUrl="~/home.aspx" loginUrl="~/login.aspx"
slidingExpiration="true" timeout="2880"></forms>
</authentication>

<authorization>
<deny users="?" />
</authorization>
</system.web>
</configuration>

La section de configuration authentication configure l’authentification par formulaire


pour l’application. La section authorization est utilisée pour interdire les utilisateurs
anonymes pour l’ensemble de l’application. Toutefois, vous pouvez fournir des règles
d’autorisation plus granulaires par emplacement et appliquer des vérifications
d’autorisation basées sur des rôles.

XML

<location path="login.aspx">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>

La configuration ci-dessus, lorsqu’elle est combinée à la première, permet aux


utilisateurs anonymes d’accéder à la page de connexion, en remplaçant la restriction à
l’échelle du site sur les utilisateurs non authentifiés.

XML
<location path="/admin">
<system.web>
<authorization>
<allow roles="Administrators" />
<deny users="*" />
</authorization>
</system.web>
</location>

La configuration ci-dessus, lorsqu’elle est combinée aux autres, limite l’accès au dossier
/admin et toutes les ressources qu’il contient aux membres du rôle « Administrateurs ».
Cette restriction peut également être appliquée en plaçant un fichier web.config distinct
dans la racine du dossier /admin .

Code d’autorisation dans Web Forms


Outre la configuration de l’accès à l’aide de web.config , vous pouvez également
configurer par programmation l’accès et le comportement dans votre application Web
Forms. Par exemple, vous pouvez restreindre la possibilité d’effectuer certaines
opérations ou d’afficher certaines données en fonction du rôle de l’utilisateur.

Ce code peut être utilisé à la fois dans la logique code-behind et dans la page elle-
même :

HTML

<% if (HttpContext.Current.User.IsInRole("Administrators")) { %>


<a href="/admin">Go To Admin</a>
<% } %>

En plus de vérifier l’appartenance au rôle d’utilisateur, vous pouvez également


déterminer s’ils sont authentifiés (bien que cela soit souvent mieux fait à l’aide de la
configuration basée sur l’emplacement décrite ci-dessus). Voici un exemple de cette
approche.

C#

protected void Page_Load(object sender, EventArgs e)


{
if (!User.Identity.IsAuthenticated)
{
FormsAuthentication.RedirectToLoginPage();
}
if (!Roles.IsUserInRole(User.Identity.Name, "Administrators"))
{
MessageLabel.Text = "Only administrators can view this.";
SecretPanel.Visible = false;
}
}

Dans le code ci-dessus, le contrôle d’accès en fonction du rôle (RBAC) est utilisé pour
déterminer si certains éléments de la page, tels qu’un SecretPanel , sont visibles en
fonction du rôle de l’utilisateur actuel.

En règle générale, les applications ASP.NET Web Forms configurent la sécurité dans le
fichier web.config , puis ajoutent des vérifications supplémentaires si nécessaire dans les
pages .aspx et leurs fichiers code-behind .aspx.cs associés. La plupart des applications
tirent parti du fournisseur d’appartenance universel, fréquemment avec le fournisseur de
rôles supplémentaires.

Identité ASP.NET Core


Bien que toujours chargé de l’authentification et de l’autorisation, ASP.NET Core Identity
utilise un ensemble différent d’abstractions et d’hypothèses par rapport aux fournisseurs
universels. Par exemple, le nouveau modèle Identity prend en charge l’authentification
tierce, ce qui permet aux utilisateurs de s’authentifier à l’aide d’un compte de réseaux
sociaux ou d’un autre fournisseur d’authentification approuvé. ASP.NET Core Identity
prend en charge l’interface utilisateur pour les pages couramment nécessaires, telles
que la connexion, la déconnexion et l’inscription. L’API tire parti d’EF Core pour son
accès aux données et utilise les migrations EF Core pour générer le schéma nécessaire
pour prendre en charge son modèle de données. Cette introduction à Identity on
ASP.NET Core fournit une bonne vue d’ensemble de ce qui est inclus avec ASP.NET Core
Identity et comment commencer à l’utiliser. Si vous n’avez pas encore configuré
ASP.NET Core Identity dans votre application et sa base de données, cela vous aidera à
commencer.

Rôles, revendications et stratégies


Les fournisseurs universels et ASP.NET Core Identity prennent en charge le concept de
rôles. Vous pouvez créer des rôles pour les utilisateurs et affecter des utilisateurs à des
rôles. Les utilisateurs peuvent appartenir à un nombre quelconque de rôles, et vous
pouvez vérifier l’appartenance aux rôles dans le cadre de votre implémentation
d’autorisation.

En plus des rôles, ASP.NET Core Identity prend en charge les concepts des
revendications et des stratégies. Bien qu’un rôle corresponde spécifiquement à un
ensemble de ressources auxquelles un utilisateur dans ce rôle doit pouvoir accéder, une
revendication fait simplement partie de l’identité d’un utilisateur. Une revendication est
une paire valeur de nom qui représente ce que l’objet est, et non ce que le sujet peut
faire.

Il est possible d’inspecter directement les revendications d’un utilisateur et de


déterminer en fonction de ces valeurs si un utilisateur doit avoir accès à une ressource.
Toutefois, ces vérifications sont souvent répétitives et dispersées dans tout le système.
Une meilleure approche consiste à définir une stratégie.

Une stratégie d’autorisation se compose d’une ou plusieurs exigences. Les stratégies


sont inscrites dans le cadre de la configuration du service d’autorisation dans la
méthode ConfigureServices de Startup.cs . Par exemple, l’extrait de code suivant
configure une stratégie appelée « CanadiensOnly », qui a l’exigence que l’utilisateur a la
revendication Country avec la valeur « Canada ».

C#

services.AddAuthorization(options =>
{
options.AddPolicy("CanadiansOnly", policy =>
policy.RequireClaim(ClaimTypes.Country, "Canada"));
});

Vous pouvez en savoir plus sur la création de stratégies personnalisées dans la


documentation.

Que vous utilisiez des stratégies ou des rôles, vous pouvez spécifier qu’une page
particulière dans votre application Blazor nécessite ce rôle ou cette stratégie avec
l’attribut [Authorize] , appliqué avec la directive @attribute .

Exiger un rôle :

C#

@attribute [Authorize(Roles ="administrators")]

Exiger qu’une stratégie soit satisfaite :

C#

@attribute [Authorize(Policy ="CanadiansOnly")]

Si vous avez besoin d’accéder à l’état d’authentification, aux rôles ou aux revendications
d’un utilisateur dans votre code, il existe deux façons principales d’obtenir cette
fonctionnalité. La première consiste à recevoir l’état d’authentification en tant que
paramètre en cascade. La seconde consiste à accéder à l’état à l’aide d’un
AuthenticationStateProvider injecté. Les détails de chacune de ces approches sont

décrits dans la documentation de sécurité Blazor.

Le code suivant montre comment recevoir AuthenticationState en tant que paramètre


en cascade :

C#

[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }

Avec ce paramètre en place, vous pouvez obtenir l’utilisateur à l’aide de ce code :

C#

var authState = await authenticationStateTask;


var user = authState.User;

Le code suivant montre comment injecter AuthenticationStateProvider :

C#

@using Microsoft.AspNetCore.Components.Authorization
@inject AuthenticationStateProvider AuthenticationStateProvider

Avec le fournisseur en place, vous pouvez accéder à l’utilisateur avec le code suivant :

C#

AuthenticationState authState = await


AuthenticationStateProvider.GetAuthenticationStateAsync();
ClaimsPrincipal user = authState.User;

if (user.Identity.IsAuthenticated)
{
// work with user.Claims and/or user.Roles
}

Remarque : Le composant AuthorizeView , abordé plus loin dans ce chapitre, fournit un


moyen déclaratif de contrôler ce qu’un utilisateur voit sur une page ou un composant.

Pour travailler avec les utilisateurs et les revendications (dans des applications Blazor
Server) vous devrez peut-être également injecter un UserManager<T> (utilisez
IdentityUser par défaut) que vous pouvez utiliser pour énumérer et modifier les

revendications d’un utilisateur. Commencez par injecter le type et l’affecter à une


propriété :

C#

@inject UserManager<IdentityUser> MyUserManager

Utilisez-la ensuite pour utiliser les revendications de l’utilisateur. L’exemple suivant


montre comment ajouter et conserver une revendication sur un utilisateur :

C#

private async Task AddCountryClaim()


{
var authState = await
AuthenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
var identityUser = await
MyUserManager.FindByNameAsync(user.Identity.Name);

if (!user.HasClaim(c => c.Type == ClaimTypes.Country))


{
// stores the claim in the cookie
ClaimsIdentity id = new ClaimsIdentity();
id.AddClaim(new Claim(ClaimTypes.Country, "Canada"));
user.AddIdentity(id);

// save the claim in the database


await MyUserManager.AddClaimAsync(identityUser, new
Claim(ClaimTypes.Country, "Canada"));
}
}

Si vous avez besoin d’utiliser des rôles, suivez la même approche. Vous devrez peut-être
injecter un RoleManager<T> (utilisez IdentityRole pour le type par défaut) pour
répertorier et gérer les rôles eux-mêmes.

Note : Dans les projets Blazor WebAssembly, vous devez fournir des API serveur pour
effectuer ces opérations (au lieu d’utiliser UserManager<T> ou RoleManager<T>
directement). Une application cliente Blazor WebAssembly gérerait les revendications
et/ou les rôles en appelant en toute sécurité les points de terminaison d’API exposés à
cet effet.

Guide de migration
La migration d’ASP.NET Web Forms et de fournisseurs universels vers ASP.NET Core
Identity nécessite plusieurs étapes :

1. Créer un schéma de base de données ASP.NET Core Identity dans la base de


données de destination
2. Migrer des données d’un schéma de fournisseur universel vers un schéma ASP.NET
Core Identity
3. Migrer la configuration de web.config vers les intergiciels et les services,
généralement dans Program.cs (ou une classe Startup )
4. Mettez à jour des pages individuelles à l’aide de contrôles et de conditions pour
utiliser l’assistance des balises et de nouvelles API d’identité.

Chacune de ces étapes est décrite en détail dans les sections suivantes.

Création du schéma ASP.NET Core Identity


Il existe plusieurs façons de créer la structure de table nécessaire pour ASP.NET Core
Identity. Le plus simple est de créer une application web ASP.NET Core. Choisissez
Application web, puis modifiez le type d’authentification pour utiliser Comptes
individuels.

À partir de la ligne de commande, vous pouvez faire la même chose en exécutant


dotnet new webapp -au Individual . Une fois l’application créée, exécutez-la et inscrivez-

la sur le site. Vous devez déclencher une page comme celle illustrée ci-dessous :
Cliquez sur le bouton « Appliquer des migrations » et les tables de base de données
nécessaires doivent être créées pour vous. En outre, les fichiers de migration doivent
apparaître dans votre projet, comme indiqué :

Vous pouvez exécuter la migration vous-même, sans exécuter l’application web, à l’aide
de cet outil en ligne de commande :

PowerShell
dotnet ef database update

Si vous préférez exécuter un script pour appliquer le nouveau schéma à une base de
données existante, vous pouvez scripter ces migrations à partir de la ligne de
commande. Exécutez cette commande pour générer le script :

PowerShell

dotnet ef migrations script -o auth.sql

La commande ci-dessus génère un script SQL dans le fichier de sortie auth.sql , qui
peut ensuite être exécuté sur la base de données souhaitée. Si vous rencontrez des
problèmes lors de l’exécution des commandes dotnet ef , assurez-vous que les outils EF
Core sont installés sur votre système.

Si vous avez des colonnes supplémentaires sur vos tables sources, vous devez identifier
le meilleur emplacement pour ces colonnes dans le nouveau schéma. En règle générale,
les colonnes trouvées sur la table aspnet_Membership doivent être mappées à la table
AspNetUsers . Les colonnes sur aspnet_Roles doivent être mappées à AspNetRoles .

Toutes les colonnes supplémentaires de la table aspnet_UsersInRoles sont ajoutées à la


table AspNetUserRoles .

Cela vaut également la peine d’envisager de placer des colonnes supplémentaires sur
des tables distinctes. Ainsi, les migrations futures n’auront pas besoin de tenir compte
de ces personnalisations du schéma d’identité par défaut.

Migration de données de fournisseurs universels vers


ASP.NET Core Identity
Une fois le schéma de table de destination en place, l’étape suivante consiste à migrer
vos enregistrements d’utilisateur et de rôle vers le nouveau schéma. Une liste complète
des différences de schéma, y compris les colonnes mappées aux nouvelles colonnes, se
trouve ici.

Pour migrer vos utilisateurs de l’appartenance aux nouvelles tables d’identité, vous
devez suivre les étapes décrites dans la documentation. Après avoir suivi ces étapes et le
script fourni, vos utilisateurs devront modifier leur mot de passe la prochaine fois qu’ils
se connecteront.

Il est possible de migrer les mots de passe utilisateur, mais le processus est beaucoup
plus impliqué. Exiger des utilisateurs de mettre à jour leurs mots de passe dans le cadre
du processus de migration et les encourager à utiliser de nouveaux mots de passe
uniques est susceptible d’améliorer la sécurité globale de l’application.

Migration des paramètres de sécurité de web.config vers


le démarrage de l’application
Comme indiqué ci-dessus, les fournisseurs d’appartenance et de rôle ASP.NET sont
configurés dans le fichier web.config . Étant donné que les applications ASP.NET Core ne
sont pas liées à IIS et utilisent un système distinct pour la configuration, ces paramètres
doivent être configurés ailleurs. Dans la plupart des cas, ASP.NET Core Identity est
configuré dans le fichier Program.cs. Ouvrez le projet web créé précédemment (pour
générer le schéma de la table d’identité) et passez en revue son fichier Program.cs (ou
Startup.cs).

Ce code ajoute la prise en charge d’EF Core et Identity :

C#

// Add services to the container.


var connectionString =
builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options =>
options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();

La méthode d’extension AddDefaultIdentity est utilisée pour configurer Identity pour


utiliser la classe ApplicationDbContext et le type IdentityUser de l’infrastructure. Si vous
utilisez un IdentityUser personnalisé, veillez à spécifier son type ici. Si ces méthodes
d’extension ne fonctionnent pas dans votre application, vérifiez que vous disposez des
instructions appropriées et que vous disposez des références de package NuGet
nécessaires. Par exemple, votre projet doit avoir une version des packages
Microsoft.AspNetCore.Identity.EntityFrameworkCore et

Microsoft.AspNetCore.Identity.UI référencés.

En outre, dans Program.cs vous devez voir l’intergiciel nécessaire configuré pour le site.
Plus précisément, UseAuthentication et UseAuthorization doivent être configurés et à
l’emplacement approprié.

C#
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for
production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

//app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

ASP.NET Identity ne configure pas l’accès anonyme ou en fonction du rôle aux


emplacements à partir de Program.cs. Vous devez migrer les données de configuration
d’autorisation spécifiques à l’emplacement vers des filtres dans ASP.NET Core. Notez
quels dossiers et pages nécessitent ces mises à jour. Vous allez apporter ces
modifications dans la section suivante.

Mise à jour de pages individuelles pour utiliser des


abstractions ASP.NET Core Identity
Dans votre application ASP.NET Web Forms, si vous aviez des paramètres web.config
pour refuser l’accès à certaines pages ou certains dossiers à des utilisateurs anonymes,
vous migreriez ces modifications en ajoutant l’attribut [Authorize] à ces pages :

razor

@attribute [Authorize]

Si, de plus, vous refusiez l’accès sauf aux utilisateurs appartenant à un certain rôle, vous
migreriez pareillement ce comportement en ajoutant un attribut spécifiant un rôle :
razor

@attribute [Authorize(Roles ="administrators")]

L’attribut [Authorize] fonctionne uniquement sur des composants @page qui sont
atteints via le routeur Blazor. L’attribut ne fonctionne pas avec les composants enfants,
qui doivent utiliser à la place AuthorizeView .

Si vous avez une logique dans la balise de page pour déterminer s’il faut afficher du
code à un utilisateur donné, vous pouvez la remplacer par le composant AuthorizeView .
Le composant AuthorizeView affiche sélectivement l’interface utilisateur en fonction de
l’autorisation que l’utilisateur a pour l’afficher. Il expose également une variable context
qui peut être utilisée pour accéder aux informations utilisateur.

razor

<AuthorizeView>
<Authorized>
<h1>Hello, @context.User.Identity.Name!</h1>
<p>You can only see this content if you are authenticated.</p>
</Authorized>
<NotAuthorized>
<h1>Authentication Failure!</h1>
<p>You are not signed in.</p>
</NotAuthorized>
</AuthorizeView>

Vous pouvez accéder à l’état d’authentification dans la logique procédurale en accédant


à l’utilisateur à partir d’une classe Task<AuthenticationState configurée avec l’attribut
[CascadingParameter] . Cette configuration vous permet d’accéder à l’utilisateur, ce qui

vous permet de déterminer s’il est authentifié et s’il appartient à un rôle particulier. Si
vous devez évaluer une stratégie de façon procédurale, vous pouvez injecter une
instance de IAuthorizationService et appeler la méthode AuthorizeAsync sur celle-ci.
L’exemple de code suivant montre comment obtenir des informations utilisateur et
autoriser un utilisateur autorisé à effectuer une tâche restreinte par la stratégie content-
editor .

razor

@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService

<button @onclick="@DoSomething">Do something important</button>

@code {
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }

private async Task DoSomething()


{
var user = (await authenticationStateTask).User;

if (user.Identity.IsAuthenticated)
{
// Perform an action only available to authenticated (signed-in)
users.
}

if (user.IsInRole("admin"))
{
// Perform an action only available to users in the 'admin'
role.
}

if ((await AuthorizationService.AuthorizeAsync(user, "content-


editor"))
.Succeeded)
{
// Perform an action only available to users satisfying the
// 'content-editor' policy.
}
}
}

AuthenticationState doit d’abord être configuré comme valeur en cascade avant de


pouvoir être lié à un paramètre en cascade comme suit. Cela est généralement fait à
l’aide du composant CascadingAuthenticationState . Cette configuration est
généralement effectuée dans App.razor :

razor

<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData"
DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
Résumé
Blazor utilise le même modèle de sécurité qu’ASP.NET Core, qui est ASP.NET Core
Identity. La migration de fournisseurs universels vers ASP.NET Core Identity est
relativement simple, en supposant qu’aucune personnalisation n’a été appliquée au
schéma de données d’origine. Une fois les données migrées, l’utilisation de
l’authentification et de l’autorisation dans les applications Blazor est bien documentée,
avec une prise en charge configurable et de programmation pour la plupart des
exigences de sécurité.

References
Introduction à Identity sur ASP.NET Core
Migrer de l’authentification d’appartenance ASP.NET vers ASP.NET Core 2.0
Identity
Migrer l’authentification et l’identité vers ASP.NET Core
Authentification et autorisation avec ASP.NET Core Blazor

Précédent Suivant
Migrer à partir d’ASP.NET Web Forms
vers Blazor
Article • 08/06/2023

 Conseil

Ce contenu est un extrait du livre électronique, Blazor pour les développeurs ASP
NET Web Forms pour Azure, disponible dans la documentation .NET ou au format
PDF à télécharger gratuitement pour le lire hors connexion.

Télécharger le PDF

La migration d’une base de code à partir d’ASP.NET Web Forms vers Blazor est une
tâche fastidieuse qui nécessite une planification. Ce chapitre décrit le processus. Une
solution qui permet de faciliter la transition consiste à s’assurer que l’application
respecte une architecture multiniveau, où le modèle d’application (dans ce cas, Web
Forms) est distinct de la logique métier. Cette séparation logique des couches indique
clairement ce qui doit être déplacé vers .NET Core et Blazor.

Pour cet exemple, l’application eShop disponible sur GitHub est utilisée. eShop est un
service de catalogue qui fournit des capacités CRUD via l’entrée de formulaire et la
validation.

Pourquoi une application opérationnelle doit-elle être migrée vers Blazor ? Beaucoup de
fois, il n’y a pas besoin. ASP.NET Web Forms continuera d’être pris en charge pendant
de nombreuses années. Toutefois, la plupart des fonctionnalités fournies par Blazor sont
uniquement prises en charge sur une application migrée. Les fonctionnalités incluent :

Améliorations des performances dans l’infrastructure, telles que Span<T>


Possibilité de s’exécuter en tant que WebAssembly
Prise en charge multiplateforme pour Linux et macOS
Déploiement local d’applications ou déploiement de framework partagé sans
impact sur d’autres applications

Si ces fonctionnalités ou d’autres nouvelles fonctionnalités sont suffisamment


attrayantes, il peut y avoir une valeur dans la migration de l’application. La migration
peut prendre différentes formes ; il peut s’agir de l’ensemble de l’application ou de
certains points de terminaison qui nécessitent les modifications. La décision de migrer
est finalement basée sur les problèmes métier à résoudre par le développeur.

Hébergement côté serveur et côté client


Comme décrit dans le chapitre des modèles d’hébergement, une application Blazor peut
être hébergée de deux façons différentes : côté serveur et côté client. Le modèle côté
serveur utilise des connexions ASP.NET Core SignalR pour gérer les mises à jour DOM
lors de l’exécution de tout code réel sur le serveur. Le modèle côté client s’exécute en
tant que WebAssembly dans un navigateur et ne nécessite aucune connexion de
serveur. Il existe plusieurs différences qui peuvent affecter ce qui convient le mieux à
une application spécifique :

L’exécution en tant que WebAssembly ne prend pas en charge toutes les


fonctionnalités (telles que le threading) à l’heure actuelle
Une communication importante entre le client et le serveur peut entraîner des
problèmes de latence en mode côté serveur
L’accès aux bases de données et aux services internes ou protégés nécessite un
service distinct avec l’hébergement côté client

Au moment de l’écriture, le modèle côté serveur ressemble plus Web Forms. La plupart
de ce chapitre se concentre sur le modèle d’hébergement côté serveur, car il est prêt
pour la production.

Créer un projet
Cette étape de migration initiale consiste à créer un projet. Ce type de projet est basé
sur les projets de style SDK de .NET et simplifie une grande partie de la réutilisable
utilisée dans les formats de projet précédents. Pour plus d’informations, consultez le
chapitre sur la Structure de projet.

Une fois le projet créé, installez les bibliothèques utilisées dans le projet précédent. Dans
les anciens projets Web Forms, vous avez peut-être utilisé le fichier packages.config pour
répertorier les packages NuGet requis. Dans le nouveau projet de style SDK,
packages.config a été remplacé par des éléments <PackageReference> dans le fichier
projet. L’un des avantages de cette approche est que toutes les dépendances sont
installées de manière transitive. Vous listez uniquement les dépendances de niveau
supérieur qui vous intéressent.

La plupart des dépendances que vous utilisez sont disponibles pour .NET, notamment
Entity Framework 6 et log4net. Si aucune version .NET ou .NET Standard n’est
disponible, la version du .NET Framework peut souvent être utilisée. Votre kilométrage
peut varier. Toute API utilisée qui n’est pas disponible dans .NET provoque une erreur de
runtime. Visual Studio vous informe de la présence de tels paquets. Une icône jaune
s’affiche sur le nœud Références du projet dans Explorateur de solutions.

Dans le projet eShop basé sur Blazor, vous pouvez voir les packages installés.
Auparavant, le fichier packages.config listait chaque package utilisé dans le projet, ce qui
entraînait une fichier de près de 50 lignes de long. Un extrait de code de packages.config
est :

XML

<?xml version="1.0" encoding="utf-8"?>


<packages>
...
<package id="Microsoft.ApplicationInsights.Agent.Intercept"
version="2.4.0" targetFramework="net472" />
<package id="Microsoft.ApplicationInsights.DependencyCollector"
version="2.9.1" targetFramework="net472" />
<package id="Microsoft.ApplicationInsights.PerfCounterCollector"
version="2.9.1" targetFramework="net472" />
<package id="Microsoft.ApplicationInsights.Web" version="2.9.1"
targetFramework="net472" />
<package id="Microsoft.ApplicationInsights.WindowsServer" version="2.9.1"
targetFramework="net472" />
<package id="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel"
version="2.9.1" targetFramework="net472" />
<package id="Microsoft.AspNet.FriendlyUrls" version="1.0.2"
targetFramework="net472" />
<package id="Microsoft.AspNet.FriendlyUrls.Core" version="1.0.2"
targetFramework="net472" />
<package id="Microsoft.AspNet.ScriptManager.MSAjax" version="5.0.0"
targetFramework="net472" />
<package id="Microsoft.AspNet.ScriptManager.WebForms" version="5.0.0"
targetFramework="net472" />
...
<package id="System.Memory" version="4.5.1" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.4.0"
targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.0"
targetFramework="net472" />
<package id="System.Threading.Channels" version="4.5.0"
targetFramework="net472" />
<package id="System.Threading.Tasks.Extensions" version="4.5.1"
targetFramework="net472" />
<package id="WebGrease" version="1.6.0" targetFramework="net472" />
</packages>

L’élément <packages> inclut toutes les dépendances nécessaires. Il est difficile


d’identifier quels packages sont inclus, car vous en avez besoin. Certains éléments
<package> sont répertoriés simplement pour répondre aux besoins des dépendances

dont vous avez besoin.

Le projet Blazor répertorie les dépendances dont vous avez besoin dans un élément
<ItemGroup> dans le fichier projet :

XML

<ItemGroup>
<PackageReference Include="Autofac" Version="4.9.3" />
<PackageReference Include="EntityFramework" Version="6.4.4" />
<PackageReference Include="log4net" Version="2.0.12" />
<PackageReference
Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="2.2.12"
/>
</ItemGroup>

Un package NuGet qui simplifie la durée de vie des développeurs Web Forms est le pack
de compatibilité Windows. Bien que .NET soit multiplateforme, certaines fonctionnalités
sont disponibles uniquement sur Windows. Les fonctionnalités spécifiques à Windows
sont disponibles en installant le pack de compatibilité. Parmi ces fonctionnalités, citons
le Registre, WMI et les services d’annuaire. Le package ajoute environ 20 000 API et
active de nombreux services avec lesquels vous êtes peut-être déjà familiarisé. Le projet
eShop ne nécessite pas le pack de compatibilité ; mais si vos projets utilisent des
fonctionnalités spécifiques à Windows, le package facilite les efforts de migration.

Activer le processus de démarrage


Le processus de démarrage de Blazor n’est plus Web Forms et il suit une configuration
similaire pour d’autres services ASP.NET Core. Quand ils sont hébergés côté serveur, les
composants Razor sont exécutés dans le cadre d’une application ASP.NET Core normale.
Lorsqu’ils sont hébergés dans le navigateur avec WebAssembly, les composants Razor
utilisent un modèle d’hébergement similaire. La différence est que les composants sont
exécutés en tant que service distinct de l’un des processus back-end. Dans les deux cas,
le démarrage est similaire.
Le fichier Global.asax.cs est la page de démarrage par défaut pour les projets Web
Forms. Dans le projet eShop, ce fichier configure le conteneur Inversion of Control (IoC)
et gère les différents événements de cycle de vie de l’application ou de la demande.
Certains de ces événements sont gérés avec un intergiciel (par exemple
Application_BeginRequest ). D’autres événements nécessitent la substitution de services

spécifiques via l’injection de dépendances (DI).

Par exemple, le fichier Global.asax.cs pour eShop contient le code suivant :

C#

public class Global : HttpApplication, IContainerProviderAccessor


{
private static readonly ILog _log =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().Declari
ngType);

static IContainerProvider _containerProvider;


IContainer container;

public IContainerProvider ContainerProvider


{
get { return _containerProvider; }
}

protected void Application_Start(object sender, EventArgs e)


{
// Code that runs on app startup
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ConfigureContainer();
ConfigDataBase();
}

/// <summary>
/// Track the machine name and the start time for the session inside the
current session
/// </summary>
protected void Session_Start(Object sender, EventArgs e)
{
HttpContext.Current.Session["MachineName"] =
Environment.MachineName;
HttpContext.Current.Session["SessionStartTime"] = DateTime.Now;
}

/// <summary>
/// https://autofaccn.readthedocs.io/en/latest/integration/webforms.html
/// </summary>
private void ConfigureContainer()
{
var builder = new ContainerBuilder();
var mockData =
bool.Parse(ConfigurationManager.AppSettings["UseMockData"]);
builder.RegisterModule(new ApplicationModule(mockData));
container = builder.Build();
_containerProvider = new ContainerProvider(container);
}

private void ConfigDataBase()


{
var mockData =
bool.Parse(ConfigurationManager.AppSettings["UseMockData"]);

if (!mockData)
{
Database.SetInitializer<CatalogDBContext>
(container.Resolve<CatalogDBInitializer>());
}
}

protected void Application_BeginRequest(object sender, EventArgs e)


{
//set the property to our new object
LogicalThreadContext.Properties["activityid"] = new
ActivityIdHelper();

LogicalThreadContext.Properties["requestinfo"] = new
WebRequestInfo();

_log.Debug("Application_BeginRequest");
}
}

Le fichier précédent devient le fichier Program.cs côté serveur Blazor :

C#

using eShopOnBlazor.Models;
using eShopOnBlazor.Models.Infrastructure;
using eShopOnBlazor.Services;
using log4net;
using System.Data.Entity;
using eShopOnBlazor;

var builder = WebApplication.CreateBuilder(args);

// add services

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();

if (builder.Configuration.GetValue<bool>("UseMockData"))
{
builder.Services.AddSingleton<ICatalogService, CatalogServiceMock>();
}
else
{
builder.Services.AddScoped<ICatalogService, CatalogService>();
builder.Services.AddScoped<IDatabaseInitializer<CatalogDBContext>,
CatalogDBInitializer>();
builder.Services.AddSingleton<CatalogItemHiLoGenerator>();
builder.Services.AddScoped(_ => new
CatalogDBContext(builder.Configuration.GetConnectionString("CatalogDBContext
")));
}

var app = builder.Build();

new LoggerFactory().AddLog4Net("log4Net.xml");

if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}

// Middleware for Application_BeginRequest


app.Use((ctx, next) =>
{
LogicalThreadContext.Properties["activityid"] = new
ActivityIdHelper(ctx);
LogicalThreadContext.Properties["requestinfo"] = new
WebRequestInfo(ctx);
return next();
});

app.UseStaticFiles();

app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});

ConfigDataBase(app);

void ConfigDataBase(IApplicationBuilder app)


{
using (var scope = app.ApplicationServices.CreateScope())
{
var initializer =
scope.ServiceProvider.GetService<IDatabaseInitializer<CatalogDBContext>>();

if (initializer != null)
{
Database.SetInitializer(initializer);
}
}
}

app.Run();

Un changement important que vous remarquerez peut-être de Web Forms est


l’importance de l’injection de dépendances (DI). DI a été un principe directeur dans la
conception d’ASP.NET Core. Elle prend en charge la personnalisation de presque tous
les aspects de l’infrastructure ASP.NET Core. Il existe même un fournisseur de services
intégré qui peut être utilisé pour de nombreux scénarios. Si d’autres personnalisations
sont requises, elles peuvent être prises en charge par de nombreux projets
communautaires. Par exemple, vous pouvez transférer votre investissement de
bibliothèque de DI tiers.

Dans l’application eShop d’origine, il existe une configuration pour la gestion des
sessions. Étant donné que Blazor côté serveur utilise ASP.NET Core SignalR pour la
communication, l’état de session n’est pas pris en charge, car les connexions peuvent se
produire indépendamment d’un contexte HTTP. Une application qui utilise l’état de
session nécessite une nouvelle architecture avant de l’exécuter en tant qu’application
Blazor.

Pour plus d’informations sur le démarrage de l’application, consultez Démarrage de


l’application.

Migrer des modules et gestionnaires HTTP vers


des intergiciels
Les modules et les gestionnaires HTTP sont des modèles courants dans Web Forms pour
contrôler le pipeline de requête HTTP. Des classes qui implémentent IHttpModule ou
IHttpHandler peuvent être inscrites et traiter les demandes entrantes. Web Forms
configure des modules et des gestionnaires dans le fichier web.config. Web Forms est
également fortement basé sur la gestion des événements du cycle de vie des
applications. ASP.NET Core utilise plutôt l’intergiciel. L’intergiciel est inscrit dans la
méthode Configure de la classe Startup . L’ordre d’exécution des intergiciels est
déterminé par l’ordre d’enregistrement.

Dans la section Activer le processus de démarrage, un événement de cycle de vie a été


déclenché par Web Forms comme la méthode Application_BeginRequest . Cet
événement n’est pas disponible dans ASP.NET Core. Pour atteindre ce comportement,
vous pouvez implémenter un intergiciel comme indiqué dans l’exemple de fichier
Startup.cs. Cet intergiciel effectue la même logique, puis transfère le contrôle au
gestionnaire suivant dans le pipeline d’intergiciels.

Pour plus d’informations sur la migration de modules et de gestionnaires, consultez


Migrer des gestionnaires et des modules HTTP vers un intergiciel ASP.NET Core.

Migrer des fichiers statiques


Pour traiter des fichiers statiques (par exemple, HTML, CSS, images et JavaScript), les
fichiers doivent être exposés par intergiciel. L’appel de la méthode UseStaticFiles
active le service de fichiers statiques à partir du chemin racine du web. Le répertoire
racine web par défaut est wwwroot, mais il peut être personnalisé. Comme inclus dans le
fichier Program.cs :

C#

...

app.UseStaticFiles();

...

Le projet eShop permet d’accéder aux fichiers statiques de base. De nombreuses


personnalisations sont disponibles pour l’accès aux fichiers statiques. Pour plus
d’informations sur l’activation des fichiers par défaut ou d’un navigateur de fichiers,
consultez Fichiers statiques dans ASP.NET Core.

Migration du regroupement de runtime et de


la configuration de la minimisation
Le regroupement et la minimisation sont des techniques d’optimisation des
performances permettant de réduire le nombre et la taille des demandes de serveur
pour récupérer certains types de fichiers. JavaScript et CSS subissent souvent une forme
de regroupement ou de minimisation avant d’être envoyés au client. Dans ASP.NET Web
Forms, ces optimisations sont gérées au moment de l’exécution. Les conventions
d’optimisation sont définies dans un fichier App_Start/BundleConfig.cs. Dans ASP.NET
Core, une approche plus déclarative est adoptée. Un fichier répertorie les fichiers à
réduire, ainsi que les paramètres de minimisation spécifiques.
Pour plus d’informations sur le regroupement et la minimisation, consultez Regrouper et
minimiser les ressources statiques dans ASP.NET Core.

Migrer des pages ASPX


Une page d’une application Web Forms est un fichier avec l’extension .aspx. Une page
Web Forms peut souvent être mappée à un composant dans Blazor. Un composant
Razor est créé dans un fichier avec l’extension .razor. Pour le projet eShop, cinq pages
sont converties en page Razor.

Par exemple, la vue détails comprend trois fichiers dans le projet Web Forms :
Details.aspx, Details.aspx.cs et Details.aspx.designer.cs. Lors de la conversion en Blazor, le
code-behind et le balisage sont combinés en Details.razor. La compilation Razor
(équivalente à ce qui se trouve dans les fichiers .designer.cs) est stockée dans le
répertoire obj et n’est pas, par défaut, visible dans Explorateur de solutions. La page
Web Forms se compose du balisage suivant :

ASP.NET (C#)

<%@ Page Title="Details" Language="C#" MasterPageFile="~/Site.Master"


AutoEventWireup="true" CodeBehind="Details.aspx.cs"
Inherits="eShopLegacyWebForms.Catalog.Details" %>

<asp:Content ID="Details" ContentPlaceHolderID="MainContent" runat="server">


<h2 class="esh-body-title">Details</h2>

<div class="container">
<div class="row">
<asp:Image runat="server" CssClass="col-md-6 esh-picture"
ImageUrl='<%#"/Pics/" + product.PictureFileName%>' />
<dl class="col-md-6 dl-horizontal">
<dt>Name
</dt>

<dd>
<asp:Label runat="server" Text='<%#product.Name%>' />
</dd>

<dt>Description
</dt>

<dd>
<asp:Label runat="server"
Text='<%#product.Description%>' />
</dd>

<dt>Brand
</dt>
<dd>
<asp:Label runat="server"
Text='<%#product.CatalogBrand.Brand%>' />
</dd>

<dt>Type
</dt>

<dd>
<asp:Label runat="server"
Text='<%#product.CatalogType.Type%>' />
</dd>
<dt>Price
</dt>

<dd>
<asp:Label CssClass="esh-price" runat="server"
Text='<%#product.Price%>' />
</dd>

<dt>Picture name
</dt>

<dd>
<asp:Label runat="server"
Text='<%#product.PictureFileName%>' />
</dd>

<dt>Stock
</dt>

<dd>
<asp:Label runat="server"
Text='<%#product.AvailableStock%>' />
</dd>

<dt>Restock
</dt>

<dd>
<asp:Label runat="server"
Text='<%#product.RestockThreshold%>' />
</dd>

<dt>Max stock
</dt>

<dd>
<asp:Label runat="server"
Text='<%#product.MaxStockThreshold%>' />
</dd>

</dl>
</div>
<div class="form-actions no-color esh-link-list">
<a runat="server" href='<%# GetRouteUrl("EditProductRoute", new
{id =product.Id}) %>' class="esh-link-item">Edit
</a>
|
<a runat="server" href="~" class="esh-link-item">Back to list
</a>
</div>

</div>
</asp:Content>

Le code-behind du balisage précédent inclut le code suivant :

C#

using eShopLegacyWebForms.Models;
using eShopLegacyWebForms.Services;
using log4net;
using System;
using System.Web.UI;

namespace eShopLegacyWebForms.Catalog
{
public partial class Details : System.Web.UI.Page
{
private static readonly ILog _log =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().Declari
ngType);

protected CatalogItem product;

public ICatalogService CatalogService { get; set; }

protected void Page_Load(object sender, EventArgs e)


{
var productId = Convert.ToInt32(Page.RouteData.Values["id"]);
_log.Info($"Now loading... /Catalog/Details.aspx?id=
{productId}");
product = CatalogService.FindCatalogItem(productId);

this.DataBind();
}
}
}

Lorsqu’elle est convertie en Blazor, la page Web Forms se traduit par le code suivant :

razor

@page "/Catalog/Details/{id:int}"
@inject ICatalogService CatalogService
@inject ILogger<Details> Logger

<h2 class="esh-body-title">Details</h2>

<div class="container">
<div class="row">
<img class="col-md-6 esh-picture"
src="@($"/Pics/{_item.PictureFileName}")">

<dl class="col-md-6 dl-horizontal">


<dt>
Name
</dt>

<dd>
@_item.Name
</dd>

<dt>
Description
</dt>

<dd>
@_item.Description
</dd>

<dt>
Brand
</dt>

<dd>
@_item.CatalogBrand.Brand
</dd>

<dt>
Type
</dt>

<dd>
@_item.CatalogType.Type
</dd>
<dt>
Price
</dt>

<dd>
@_item.Price
</dd>

<dt>
Picture name
</dt>

<dd>
@_item.PictureFileName
</dd>

<dt>
Stock
</dt>

<dd>
@_item.AvailableStock
</dd>

<dt>
Restock
</dt>

<dd>
@_item.RestockThreshold
</dd>

<dt>
Max stock
</dt>

<dd>
@_item.MaxStockThreshold
</dd>

</dl>
</div>

<div class="form-actions no-color esh-link-list">


<a href="@($"/Catalog/Edit/{_item.Id}")" class="esh-link-item">
Edit
</a>
|
<a href="/" class="esh-link-item">
Back to list
</a>
</div>

</div>

@code {
private CatalogItem _item;

[Parameter]
public int Id { get; set; }

protected override void OnInitialized()


{
Logger.LogInformation("Now loading... /Catalog/Details/{Id}", Id);

_item = CatalogService.FindCatalogItem(Id);
}
}
Notez que le code et le balisage se trouvent dans le même fichier. Tous les services
requis sont rendus accessibles avec l’attribut @inject . Conformément à la directive
@page , cette page est accessible à l’itinéraire Catalog/Details/{id} . La valeur de

l’espace réservé {id} de l’itinéraire a été limitée à un entier. Comme décrit dans la
section routage, contrairement à Web Forms, un composant Razor indique explicitement
son itinéraire et tous les paramètres inclus. De nombreux contrôles Web Forms peuvent
ne pas avoir d’équivalents exacts dans Blazor. Il existe souvent un extrait de code HTML
équivalent qui servira le même objectif. Par exemple, le contrôle <asp:Label /> peut
être remplacé par un élément <label> HTML.

Validation de modèle dans Blazor


Si votre code Web Forms inclut la validation, vous pouvez transférer une grande partie
de ce que vous avez avec peu ou aucun changement. L’un des avantages de l’exécution
dans Blazor est que la même logique de validation peut être exécutée sans avoir besoin
de JavaScript personnalisé. Les annotations de données permettent une validation de
modèle facile.

Par exemple, la page Create.aspx comporte un formulaire d’entrée de données avec


validation. Voici un exemple d’extrait de code :

ASP.NET

<div class="form-group">
<label class="control-label col-md-2">Name</label>
<div class="col-md-3">
<asp:TextBox ID="Name" runat="server" CssClass="form-control">
</asp:TextBox>
<asp:RequiredFieldValidator runat="server" ControlToValidate="Name"
Display="Dynamic"
CssClass="field-validation-valid text-danger" ErrorMessage="The
Name field is required." />
</div>
</div>

Dans Blazor, le balisage équivalent est fourni dans un fichier Create.razor :

razor

<EditForm Model="_item" OnValidSubmit="@...">


<DataAnnotationsValidator />

<div class="form-group">
<label class="control-label col-md-2">Name</label>
<div class="col-md-3">
<InputText class="form-control" @bind-Value="_item.Name" />
<ValidationMessage For="(() => _item.Name)" />
</div>
</div>

...
</EditForm>

Le contexte EditForm inclut la prise en charge de la validation et peut être encapsulé


autour d’une entrée. Les annotations de données sont un moyen courant d’ajouter une
validation. Cette prise en charge de validation peut être ajoutée via le composant
DataAnnotationsValidator . Pour plus d’informations sur ce mécanisme, consultez
Formulaires Blazor et validation ASP.NET Core.

Migrer une configuration


Dans un projet Web Forms, les données de configuration sont généralement stockées
dans le fichier web.config. Les données de configuration sont accessibles avec
ConfigurationManager . Les services étaient souvent nécessaires pour analyser des objets.
Avec .NET Framework 4.7.2, la composabilité a été ajoutée à la configuration via
ConfigurationBuilders . Ces générateurs ont permis aux développeurs d’ajouter
différentes sources pour la configuration qui a ensuite été composée au moment de
l’exécution pour récupérer les valeurs nécessaires.

ASP.NET Core a introduit un système de configuration flexible qui vous permet de


définir la ou les sources de configuration utilisées par votre application et votre
déploiement. L’infrastructure ConfigurationBuilder que vous utilisez peut-être dans
votre application Web Forms a été modélisée d’après les concepts utilisés dans le
système de configuration ASP.NET Core.

L’extrait de code suivant montre comment le projet eShop Web Forms utilise web.config
pour stocker les valeurs de configuration :

XML

<configuration>
<configSections>
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection,
EntityFramework, Version=6.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="CatalogDBContext" connectionString="Data Source=
(localdb)\MSSQLLocalDB; Initial
Catalog=Microsoft.eShopOnContainers.Services.CatalogDb; Integrated
Security=True; MultipleActiveResultSets=True;"
providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="UseMockData" value="true" />
<add key="UseCustomizationData" value="false" />
</appSettings>
</configuration>

Il est courant que des secrets, tels que les chaînes de connexion de base de données,
soient stockés dans web.config. Les secrets sont inévitablement conservés dans des
emplacements non sécurisés, tels que le contrôle de code source. Avec Blazor sur
ASP.NET Core, la configuration XML précédente est remplacée par le code JSON
suivant :

JSON

{
"ConnectionStrings": {
"CatalogDBContext": "Data Source=(localdb)\\MSSQLLocalDB; Initial
Catalog=Microsoft.eShopOnContainers.Services.CatalogDb; Integrated
Security=True; MultipleActiveResultSets=True;"
},
"UseMockData": true,
"UseCustomizationData": false
}

JSON est le format de configuration par défaut. Toutefois, ASP.NET Core prend en
charge de nombreux autres formats, notamment XML. Il existe également plusieurs
formats pris en charge par la communauté.

Vous pouvez accéder aux valeurs de configuration à partir du générateur dans


Program.cs :

C#

if (builder.Configuration.GetValue<bool>("UseMockData"))
{
builder.Services.AddSingleton<ICatalogService, CatalogServiceMock>();
}
else
{
builder.Services.AddScoped<ICatalogService, CatalogService>();
builder.Services.AddScoped<IDatabaseInitializer<CatalogDBContext>,
CatalogDBInitializer>();
builder.Services.AddSingleton<CatalogItemHiLoGenerator>();
builder.Services.AddScoped(_ => new
CatalogDBContext(builder.Configuration.GetConnectionString("CatalogDBContext
")));
}

Par défaut, les variables d’environnement, les fichiers JSON (appsettings.json et


appsettings.{ Environment}.json) et les options de ligne de commande sont inscrits en
tant que sources de configuration valides dans l’objet de configuration. Les sources de
configuration sont accessibles via Configuration[key] . Une technique plus avancée
consiste à lier les données de configuration aux objets à l’aide du modèle d’options.
Pour plus d’informations sur la configuration et le modèle d’options, consultez
Configuration dans ASP.NET Core et Modèle Options dans ASP.NET Core,
respectivement.

Migrer l’accès aux données


L’accès aux données est un aspect important de n’importe quelle application. Le projet
eShop stocke les informations de catalogue dans une base de données et récupère les
données avec Entity Framework (EF) 6. Étant donné qu’EF 6 est pris en charge dans
.NET 5, le projet peut continuer à l’utiliser.

Les modifications liées à EF suivantes ont été nécessaires pour eShop :

Dans .NET Framework, l’objet DbContext accepte une chaîne du formulaire


name=ConnectionString et utilise la chaîne de connexion à partir de
ConfigurationManager.AppSettings[ConnectionString] pour se connecter. Dans

.NET Core, cela n’est pas pris en charge. La chaîne de connexion doit être fournie.
L'accès à la base de données s'est fait de manière synchrone. Bien que cela
fonctionne, la scalabilité peut souffrir. Cette logique doit être déplacée vers un
modèle asynchrone.

Bien qu’il n’y ait pas la même prise en charge native de la liaison de jeu de données,
Blazor offre une flexibilité et une puissance avec sa prise en charge C# dans une page
Razor. Par exemple, vous pouvez effectuer des calculs et afficher le résultat. Pour plus
d’informations sur les modèles de données dans Blazor, consultez le chapitre Accès aux
données.

Modifications architecturales
Enfin, il existe quelques différences architecturales importantes à prendre en compte
lors de la migration vers Blazor. La plupart de ces modifications s’appliquent à tout ce
qui est basé sur .NET Core ou ASP.NET Core.
Étant donné que Blazor s’appuie sur .NET Core, il existe des considérations à prendre en
compte pour garantir la prise en charge sur .NET Core. Parmi les principales
modifications, citons la suppression des fonctionnalités suivantes :

Plusieurs AppDomains
Communication à distance
Sécurité d'accès du code
Transparence de la sécurité

Pour plus d’informations sur les techniques permettant d’identifier les modifications
nécessaires pour prendre en charge l’exécution sur .NET Core, consultez Amener votre
code de .NET Framework vers .NET Core.

ASP.NET Core est une version réimaginée de ASP.NET et a des modifications qui
peuvent ne pas sembler évidentes initialement. Les principales modifications sont les
suivantes :

Aucun contexte de synchronisation, ce qui signifie qu’il n’y a pas


HttpContext.Current , Thread.CurrentPrincipal , ni d’autres accesseurs statiques

Pas de cliché instantané


Pas de file d'attente de requêtes

De nombreuses opérations dans ASP.NET Core sont asynchrones, ce qui facilite le


déchargement des tâches liées aux E/S. Il est important de ne jamais bloquer à l’aide de
Task.Wait() ou Task.GetResult() , qui peuvent rapidement épuiser les ressources du

pool de threads.

Conclusion de la migration
À ce stade, vous avez vu de nombreux exemples de ce qu’il faut faire pour déplacer un
projet Web Forms vers Blazor. Pour obtenir un exemple complet, consultez le projet
eShopOnBlazor .

Précédent

Vous aimerez peut-être aussi