Liste de vérification avant de migrer de .NET Framework vers .NET
· Mis à jour le: · Go Komura · .NET, .NET Framework, C#, Modernisation, Développement Windows, Migration
Télécharger la checklist Excel avec feuilles en japonais et en anglais
Changer le TargetFramework du .csproj en net10.0, mettre à jour quelques paquets NuGet, et si le build passe, c’est terminé.
… si la migration se résumait à cela, ce serait plutôt tranquille. En réalité, c’est rarement aussi simple.
Sur le terrain, les projets .NET Framework accumulent souvent des hypothèses implicites auxquelles on ne pense pas au quotidien : System.Web, WCF, Web Forms, d’anciens packages.config, web.config.install.xdt, des DLL natives, COM / ActiveX, des contrôles tiers qui ne fonctionnent qu’au design time, des hypothèses implicites en x86, des ResX dépendants du designer, d’anciens sérialiseurs, et bien d’autres encore.
C’est pourquoi ce qui compte vraiment dans une migration de .NET Framework vers .NET, c’est l’inventaire réalisé avant d’entrer dans l’implémentation. Si l’on parvient à décomposer les points à traiter avant de commencer, la migration cesse d’être « un gros pari » pour devenir « une liste de tâches à cocher une par une ».
Cet article résume ce qu’il faut vérifier avant de migrer une application métier existante en .NET Framework 4.x vers le .NET actuel. Les cibles principales sont, à peu près, les suivantes :
- Bibliothèques de classes
- Applications console
- Services Windows
- WinForms / WPF
- ASP.NET Framework (MVC / Web API / Web Forms)
- Applications utilisant WCF
- Applications utilisant EF6
Cet article a été rédigé le 15/03/2026. Les périodes de support et les recommandations des outils officiels évoluent, donc si vous le lisez longtemps après cette date, vérifiez également les informations officielles à jour.
1. D’abord, la conclusion
Commençons par poser les conclusions difficiles à remettre en cause.
- Nettoyer le côté .NET Framework avant de migrer vient en premier. Le guide officiel de Microsoft recommande lui aussi, avant le portage, de passer à .NET Framework 4.7.2 ou ultérieur, puis de terminer d’abord la conversion en
PackageReference, le passage au format SDK-style et la mise à jour des dépendances. - La difficulté est déterminée par le modèle applicatif plutôt que par le volume de code. Les bibliothèques de classes et les applications console sont relativement légères, tandis que ASP.NET Framework, Web Forms, les serveurs WCF et WF ont tendance à être lourds.
- WinForms / WPF peuvent migrer vers .NET tout en restant exclusivement Windows. Se tromper sur ce point, c’est marcher sur la mine classique : avoir migré et découvrir que l’application ne tourne toujours pas dans un conteneur Linux.
- ASP.NET Framework → ASP.NET Core est, dans les faits, une migration d’architecture. Pour une petite application, il est parfois possible d’y aller d’un coup, mais pour un système de production de grande taille, il est plus sûr de partir du principe d’une migration par étapes.
- WCF et EF6 peuvent parfois être dissociés de la migration du runtime. Le client WCF dispose de paquets pris en charge pour .NET, et EF6 peut être migré vers EF Core dans un second temps, une fois le passage à .NET moderne effectué.
- À l’inverse, la création d’AppDomain, .NET Remoting, CAS, COM+, Workflow Foundation et les dépendances à BinaryFormatter sont des signaux rouges. Si vous ne les repérez pas en amont, la charge de travail explosera plus tard.
packages.config/install.ps1/XDT/ les ressources du dossiercontent/ les DLL natives / COM / ActiveX / les hypothèses en x86 échouent facilement à l’exécution ou au design time même quand le build passe : il faut donc les passer au crible avant de commencer.- À la date de mars 2026, .NET 10 est la version LTS. Pour une nouvelle migration, il est naturel de viser comme point d’arrivée la LTS en cours.
- Une migration sans tests, sans mesures et sans plan de retour arrière est dangereuse. Migrer est moins un travail d’implémentation qu’un travail consistant à rendre visibles, une à une, les hypothèses de départ.
2. Décider d’abord s’il faut vraiment migrer maintenant
Ce qu’il faut décider en premier, ce n’est pas « comment migrer », mais si cette application doit vraiment être migrée maintenant.
Rester flou sur ce point conduit souvent soit à une migration techniquement correcte mais trop lourde pour l’activité, soit, à l’inverse, à repousser indéfiniment une migration qui serait pourtant clairement justifiée.
2.1 Rester sur .NET Framework est une décision tout à fait envisageable
.NET Framework 4.8.1 continue d’être pris en charge tant qu’il tourne sur une version de Windows elle-même supportée. Autrement dit, ce n’est pas aussi simple que « tout migrer vers .NET moderne immédiatement, sinon c’est le danger ».
Rester comporte toutefois des contraintes bien réelles.
- Impossible de sortir du tout-Windows
- Continuer à porter ASP.NET Web Forms et d’anciennes piles serveur
- Difficile de profiter des gains de performance, des nouvelles fonctionnalités du langage et de l’écosystème des versions récentes de .NET
- Décalage facile avec les hypothèses actuelles autour du cloud, des conteneurs et de la CI/CD
À l’inverse, si les dépendances suivantes sont fortes, il est raisonnable de rester pour l’instant sur .NET Framework 4.8.1 en exploitation stable, tout en préparant un plan de remplacement sur une autre voie.
- Un grand nombre d’écrans Web Forms
- La nécessité de préserver strictement la compatibilité d’un serveur WCF
- Une dépendance profonde à Workflow Foundation ou à COM+
- Des composants tiers utilisés au design time non pris en charge par .NET moderne
- Le contexte métier n’autorise pas de changements de spécification majeurs
2.2 Ce qui change selon l’option choisie
| Choix | Ce qui s’améliore | Ce qui reste / ce que l’on perd | Cas adapté |
|---|---|---|---|
| Rester sur .NET Framework 4.8.1 | Facile de conserver les actifs existants et d’exploiter de façon stable | Exclusivement Windows, ancien modèle applicatif, limites de la modernisation | Forte dépendance legacy, priorité donnée à l’activité et à une exploitation stable pour l’instant |
| Migrer vers .NET moderne en restant sur Windows | Le runtime et la chaîne d’outils peuvent être modernisés. Gains importants en performance, en expérience de développement et grâce au format SDK-style | Les dépendances aux API Windows subsistent. Pas de portabilité multiplateforme | Applications métier WinForms / WPF, services Windows, utilisation d’API Windows |
| Migrer vers .NET moderne en envisageant Linux / les conteneurs / le cloud à terme | Plus de liberté sur les cibles de déploiement. Plus facile de moderniser aussi le modèle d’exploitation | Il faut d’abord retirer les API et le modèle applicatif propres à Windows | Vous voulez orienter le back-end vers le cloud et moderniser aussi l’infrastructure |
Ce qui compte, ce n’est pas de vouloir migrer, mais de décider d’abord où l’on veut atterrir après la migration.
3. Quatre orientations à décider en amont
3.1 La version .NET visée comme point d’arrivée
Au moment de la rédaction, selon la politique de support de Microsoft, .NET 10 est la version LTS. Par ailleurs, .NET 8 LTS et .NET 9 STS doivent tous deux atteindre la fin de leur support le 10/11/2026.
Donc, pour une nouvelle migration depuis .NET Framework, sauf raison particulière, il est naturel de viser la LTS en cours comme point d’arrivée.
Le raisonnement pratique ici est simple.
- Pour une petite migration que l’on veut boucler rapidement, atterrir directement sur la LTS en cours
- Même pour un système central destiné à une exploitation de longue durée, la LTS en cours reste la base à privilégier
- « Rester sur la LTS précédente à cause d’une bibliothèque existante » peut être une raison légitime, mais il faut trancher en regardant concrètement jusqu’à quelle date elle sera maintenue
3.2 Rester exclusivement Windows, ou viser le multiplateforme à terme ?
Cette décision change radicalement les points à examiner.
- Si vous restez exclusivement sur Windows, vous pouvez suivre la voie réaliste consistant à d’abord moderniser le runtime avec WPF / WinForms et le Windows Compatibility Pack.
- Si vous visez à terme Linux ou la conteneurisation, il faut inventorier tôt les API liées à Windows telles que
System.Drawing.Common, le registre, WMI, EventLog, les services Windows, COM et Office Interop.
Commencer la migration sans avoir tranché ce point conduit tôt ou tard à des discussions qui partent dans tous les sens : « Est-ce que rester fixé sur Windows était vraiment le bon choix ? » « Non, en fait on voulait le faire tourner en conteneur. »
3.3 Tout migrer d’un coup, ou par étapes ?
Il existe globalement trois formes de migration.
- Une migration globale, proche d’un remplacement sur place (in-place)
- Une migration en side-by-side, où l’ancien et le nouveau coexistent
- Une migration incrémentale, route par route ou bibliothèque par bibliothèque
Pour les applications ASP.NET Framework en particulier, le guide de Microsoft recommande explicitement la migration incrémentale (incremental migration). Si vous ne pouvez pas arrêter la production, si le nombre de fonctionnalités est élevé, ou si les dépendances périphériques sont nombreuses, il est plus raisonnable de concevoir dès le départ la migration comme un processus par étapes.
3.4 Ce qu’il faut exclure du périmètre de cette migration
Les migrations échouent souvent parce que l’on essaie d’en faire trop à la fois.
Par exemple, faire tout ce qui suit en même temps tend à devenir très lourd :
- .NET Framework → .NET
- ASP.NET Framework → ASP.NET Core
- EF6 → EF Core
- Serveurs Windows → conteneurs Linux
- Changement de l’infrastructure d’authentification
- Changement de l’infrastructure de journalisation / supervision
- Migration de la base de données
Bien sûr, tout cela sera peut-être nécessaire un jour. Mais la question de savoir si tout doit être fait en même temps est une autre affaire.
En pratique, séparer les choses de la façon suivante fonctionne mieux :
- D’abord moderniser le runtime et la structure du projet
- Ensuite migrer le modèle applicatif
- Enfin mettre à jour l’ORM, l’authentification, le cloud et la supervision
4. Les fondations à préparer avant de commencer
Le guide de pré-portage de Microsoft est très concret sur le terrain. En résumé, il s’agit de rapprocher, avant la migration, le projet .NET Framework actuel d’un point d’entrée moderne.
4.1 Passer à .NET Framework 4.7.2 ou ultérieur
Le guide officiel recommande de cibler .NET Framework 4.7.2 ou ultérieur avant le portage. La raison est que, même lorsque .NET Standard ne reprend pas telle quelle une API existante, il devient plus facile de se rapprocher d’alternatives plus récentes.
En pratique, il est plus clair de prendre 4.8.1 comme référence si possible.
- Simple du point de vue du support
- Facile à traiter comme le point stable final côté .NET Framework
- Facilite l’adoption d’une politique du type « d’abord nettoyer côté Framework actuel »
Ce que cela change de le faire en premier
- La gestion des bibliothèques partagées
.NET Standard 2.0se stabilise plus facilement - Le bruit provenant de l’ancien runtime peut être réduit en amont
- Il devient plus facile de déterminer si un problème de compatibilité vient de l’ancienneté du Framework ou du passage à .NET moderne
4.2 Basculer vers PackageReference
Le guide de pré-portage recommande de convertir les références au format PackageReference.
Le faire en amont améliore nettement la visibilité sur la gestion des dépendances.
Ce que change le passage à PackageReference
- Les références de paquets sont regroupées dans le
csproj - Les dépendances transitives deviennent plus lisibles
- Les hypothèses de restore s’alignent avec le côté .NET moderne
- Meilleure compatibilité avec la CLI / la CI
Il y a toutefois des pièges ici.
Pièges classiques
La documentation officielle de NuGet mentionne explicitement les contraintes suivantes pour la migration de packages.config vers PackageReference :
- La migration intégrée de Visual Studio ne fonctionne pas pour les projets ASP.NET
- Les paquets dépendant de
install.ps1/uninstall.ps1peuvent ne pas fonctionner comme prévu - Les ressources du dossier
contentpeuvent être ignorées - Les transformations XDT telles que
web.config.install.xdtne sont pas appliquées - Les paquets dont la disposition des assemblies sous
libest ancienne peuvent mal se résoudre
Autrement dit, il vaut mieux ne pas considérer cela comme un simple changement de format de paquet.
L’ASP.NET classique en particulier avait fortement pour habitude de réécrire web.config lors de l’installation d’un paquet NuGet, ce qui fait ressortir facilement des hypothèses implicites lors de la migration.
4.3 Basculer vers le format SDK-style
Le guide de pré-portage recommande également de convertir vers le format de projet SDK-style.
Cela a un impact considérable.
Ce que change le format SDK-style
- Le
csprojdevient nettement plus concis - Bonne compatibilité avec
PackageReference - Facilite le multi-targeting
- Facile à centrer sur une CI/CD basée sur
dotnet build/dotnet test/dotnet publish - Se rapproche de la configuration côté .NET moderne, réduisant l’écart en fin de parcours
Autrement dit, sauter directement vers .NET moderne en conservant un ancien csproj et une gestion NuGet ancienne produit un écart bien trop important.
4.4 Mettre à jour les dépendances en amont
Toujours conformément au guide officiel, il s’agit de rapprocher les dépendances des dernières versions disponibles, et si possible de versions compatibles .NET Standard.
Pourquoi le faire en amont
- On sait rapidement si « ce paquet fonctionne sur .NET moderne »
- Évite que d’anciennes dépendances ne deviennent du bruit
- Facilite la conversion des bibliothèques partagées en
netstandard2.0 - Permet de concentrer le travail de migration ultérieur sur « le portage du code »
4.5 Vérifier aussi les prérequis des outils officiels
En mars 2026, le centre de gravité des recommandations de Microsoft s’est déplacé vers la modernisation via GitHub Copilot. Plutôt que de s’appuyer uniquement sur les outils d’assistance à la migration traditionnels, il est plus réaliste de considérer cela comme un flux d’assistance complet couvrant l’évaluation, la planification, les corrections de code et la validation.
La documentation actuelle suppose toutefois Visual Studio 2026 ou une version de la lignée Visual Studio 2022 encore supportée, GitHub Copilot, et du code C#.
Pourquoi cette vérification est nécessaire
- Ce que l’on peut attendre des outils officiels change
- Permet d’aligner les hypothèses de l’équipe concernant l’IDE, les agents de build et les extensions
- Permet de décider de ne pas trop compter sur l’automatisation pour les solutions VB.NET
Les projets mêlant du VB.NET ne sont pas rares. Il vaut donc la peine de vérifier dès le départ jusqu’où les derniers outils officiels peuvent réellement aider.
5. Estimer la difficulté selon le type de projet
On parle souvent de la migration « de .NET Framework vers .NET » comme d’un tout, mais en réalité, chaque type de projet est un jeu différent.
5.1 Un aperçu global de la difficulté
| Type | Difficulté | Points principaux |
|---|---|---|
| Bibliothèque de classes | Faible à moyenne | Compatibilité des API, dépendances, découpage des cibles |
| Console / traitement par lot / certains services Windows | Faible à moyenne | Mode de distribution, dépendances natives, configuration |
| WinForms / WPF | Moyenne | Reste exclusivement Windows ; designer, UI tierces, environs de BinaryFormatter |
| ASP.NET MVC / Web API | Moyenne à élevée | Migration du modèle applicatif vers ASP.NET Core, authentification, session, configuration, DI |
| ASP.NET Web Forms | Élevée | Grand écart de modèle d’écran ; suppose le remplacement de la couche UI |
| Client WCF | Moyenne | Remplacement de paquets, contrats, configuration |
| Serveur WCF | Élevée | CoreWCF ou refonte en gRPC / API HTTP |
| EF6 → EF Core en même temps | Élevée | ORM totalement différent, différences de comportement, historique de migrations |
5.2 Pour les bibliothèques de classes, la clé est de bien découper la « frontière partagée »
Les bibliothèques de classes sont relativement faciles à migrer. Mais cela n’est vrai que lorsque la bibliothèque est réellement isolée comme une bibliothèque devrait l’être.
La difficulté augmente en présence de dépendances comme les suivantes :
- Toucher à
System.Web - Lire directement
HttpContext.Current - Exposer des types WPF / WinForms dans l’API publique
- Dépendre fortement d’API Windows telles que le registre, WMI, EventLog
- Dépendre d’
AppDomainou de Remoting
Une manière simple de voir les choses : si l’on peut extraire uniquement la logique métier, c’est léger ; si la bibliothèque a englouti le modèle applicatif, c’est lourd.
5.3 WinForms / WPF migrent facilement, mais restent exclusivement Windows
WinForms et WPF peuvent être migrés vers .NET. Mais dans les deux cas, ils restent des frameworks exclusivement Windows.
Se tromper sur ce qu’il faut en attendre ici est dangereux.
- Ce qui s’améliore
- Bénéficier du runtime, du langage et du format SDK-style de .NET moderne
- Facile de rapprocher la CI/CD et la gestion des paquets des pratiques actuelles
- Facile d’obtenir certains gains de performance et de maintenabilité
- Ce qui ne change pas
- Rester exclusivement Windows
- Les problèmes de compatibilité des contrôles UI et des composants design-time subsistent
- Les problèmes liés à ActiveX / COM / DLL natives ne disparaissent pas
Par ailleurs, il arrive que WinForms / WPF nécessitent de vérifier l’impact de BinaryFormatter. En particulier lorsque des types personnalisés interviennent dans le presse-papiers, le glisser-déposer, les ResX ou la sérialisation au design time, le problème a tendance à ressortir lorsqu’on relève la cible vers .NET 9 ou ultérieur.
5.4 ASP.NET Framework relève d’une « migration du modèle applicatif », pas d’une « migration du runtime »
La migration d’ASP.NET Framework vers ASP.NET Core est explicitement qualifiée de non-trivial dans le guide de Microsoft. Ce n’est pas simplement parce que les noms d’API changent, mais parce que l’architecture sous-jacente est différente.
Les différences apparaissent principalement autour des éléments suivants :
- Hosting model
- Middleware pipeline
- Request processing model
- Session / Cache
- Authentication / Authorization
- Configuration
- Dependency Injection
- Logging / Monitoring
Pour une application ASP.NET Framework, voici ce qu’il convient de vérifier en premier :
- Quelles routes / quels endpoints peuvent être migrés en premier
- Peut-on retirer la dépendance à
System.Webdes bibliothèques partagées - Comment harmoniser l’authentification, la session, la gestion des exceptions et la journalisation
- Faut-il migrer par étapes sans arrêter la production
Pour les applications de grande taille en particulier, il est plus réaliste de partir du principe d’une migration incrémentale (incremental migration) dès le départ.
5.5 Pour Web Forms, commencer par « décomposer les responsabilités », pas par « migrer les actifs »
Web Forms n’est pas le même modèle applicatif qu’ASP.NET Core. Pour l’estimation, il est donc plus sûr de ne pas partir du principe que les écrans peuvent être repris tels quels.
En pratique, on commence souvent par la décomposition suivante :
- Séparer la logique d’écran de la logique métier
- Décomposer les responsabilités enfouies dans
Page/UserControl/ViewState - Extraire la logique métier et l’accès aux données vers des bibliothèques partagées
- Reconstruire l’UI selon un autre modèle : Razor Pages, MVC, Blazor, etc.
Autrement dit, pour un projet Web Forms, l’existence d’un plan de décomposition des responsabilités compte davantage que la migration du runtime elle-même.
5.6 Distinguer le client WCF du serveur WCF
Mieux vaut ne pas mettre les deux dans le même panier.
Client WCF
Le client WCF dispose de paquets NuGet pris en charge pour .NET moderne. Donc, si l’on se limite au côté appelant de WCF, la charge peut être moins lourde qu’il n’y paraît.
Serveur WCF
Héberger un service WCF, en revanche, est une tout autre affaire. Le guide de Microsoft présente globalement deux voies de modernisation :
- Utiliser CoreWCF pour préserver la compatibilité avec les clients existants
- Basculer vers une pile RPC / HTTP moderne telle que gRPC
Notez que CoreWCF ne reprend pas la totalité de WCF telle quelle : c’est un sous-ensemble. Il convient bien pour préserver la compatibilité avec les clients existants, mais des modifications de code et des tests sont incontournables.
6. Recenser les technologies indisponibles sur .NET ou source de blocages fréquents
C’est un point à traiter absolument avant de commencer. Microsoft tient une liste des technologies disponibles sur .NET Framework mais indisponibles sur .NET 6+.
6.1 Technologies qui deviennent souvent des signaux rouges
| Technologie | État sur .NET | Comment l’aborder |
|---|---|---|
Création d’AppDomain, comme AppDomain.CreateDomain |
Non prise en charge | Envisager l’isolation via des processus séparés / des conteneurs / AssemblyLoadContext |
| .NET Remoting | Non pris en charge | Refonte autour de l’IPC, HTTP, gRPC, sockets, pipes, etc. |
| CAS / Security Transparency | Non pris en charge comme frontière de sécurité | Envisager la séparation via l’OS / les conteneurs / les privilèges |
System.EnterpriseServices (COM+) |
Non pris en charge | Isoler et remplacer les conceptions reposant sur COM+ |
| Workflow Foundation | Non pris en charge | À estimer séparément, en tenant compte d’alternatives comme CoreWF |
| Serveur WCF | Non disponible tel quel en natif | Choisir entre CoreWCF ou gRPC |
| BinaryFormatter | Sur .NET 9+, l’implémentation lève systématiquement une exception | Migrer le sérialiseur ; auditer les ResX / le presse-papiers / le glisser-déposer |
6.2 AppDomain : « certaines API subsistent, mais la création reste un problème à part »
Le sujet AppDomain est un peu délicat.
Une partie de la surface d’API subsiste bien sur .NET, mais l’usage consistant à créer un nouvel AppDomain pour isoler du code n’est pas pris en charge.
Une refonte est donc nécessaire si AppDomain était utilisé dans les buts suivants :
- Isolation de plugins
- Déchargement de code chargé dynamiquement
- Isolation de code partiellement fiable
- Séparation temporaire d’environnements d’exécution
Avant de migrer, il ne s’agit pas seulement de vérifier si le mot AppDomain apparaît, mais de comprendre à quoi AppDomain servait réellement.
6.3 Remoting est « plus profond qu’il n’y paraît »
Remoting est concerné, bien sûr, mais des délégués asynchrones comme les appels BeginInvoke() / EndInvoke() sur un délégué peuvent aussi entrer dans le périmètre concerné. Ce n’est pas Remoting à proprement parler, mais ce n’est pas pris en charge sur .NET moderne, il faut donc le recenser avant de migrer.
Il est donc plus sûr d’inclure aussi ces éléments dans vos recherches :
System.Runtime.RemotingMarshalByRefObjectRealProxyBeginInvoke(/EndInvoke(
6.4 BinaryFormatter ressurgit brutalement selon la version cible
Plus une base de code est ancienne, plus il est probable que BinaryFormatter y soit utilisé « sans que personne n’en ait vraiment conscience ».
- Données persistées
- Cache
- Stockage de session
- État des plugins
- Presse-papiers / glisser-déposer
- ResX
- Environs du designer WinForms / WPF
À partir de .NET 9, l’implémentation de BinaryFormatter n’est plus incluse dans le runtime, et l’API lève systématiquement PlatformNotSupportedException.
Ce n’est donc pas un sujet à traiter « plus tard », mais un point à auditer dès que la version cible est fixée.
6.5 Termes à rechercher (grep) en priorité
Avant de commencer, il suffit de lancer une recherche sur l’ensemble de la solution avec les termes suivants pour que la situation devienne bien plus claire.
System.Web
HttpContext.Current
System.Runtime.Remoting
MarshalByRefObject
AppDomain
BinaryFormatter
ServiceHost
ChannelFactory
System.EnterpriseServices
Workflow
packages.config
web.config.install.xdt
install.ps1
DllImport
AxInterop
Microsoft.Office.Interop
Trouver ne serait-ce qu’un seul de ces termes ne signifie pas un échec immédiat. C’est une carte permettant de savoir ce qui peut migrer par la voie standard et ce qui relève d’une voie à part.
7. Décider jusqu’où accepter une dépendance exclusive à Windows
Un malentendu fréquent lors d’une migration est de croire que « passer à .NET rend automatiquement l’application multiplateforme ». Cette magie n’existe pas. Si l’application est profondément liée à Windows, elle reste tout simplement exclusivement Windows après la migration.
7.1 Migrer en restant exclusivement Windows est une option tout à fait réaliste
Microsoft propose le Windows Compatibility Pack, un moyen d’utiliser depuis .NET moderne de nombreuses API orientées Windows : le registre, WMI, EventLog, les services Windows, Directory Services, et bien d’autres.
Son existence compte beaucoup en pratique.
- On veut d’abord passer à .NET moderne
- Mais on ne quitte pas Windows pour l’instant
- Donc on veut accepter provisoirement les dépendances aux API Windows
Dans ce genre de contexte, c’est une option solide.
Le premier objectif d’une migration n’a donc pas forcément besoin d’être la portabilité multiplateforme.
7.2 Mais les API exclusivement Windows sont aussi « une dette qui se rappellera à vous plus tard »
L’existence du Windows Compatibility Pack ne met pas tout à l’abri pour autant.
- Vous voulez déployer en conteneur Linux
- Vous voulez faire tourner l’application sous Kubernetes
- Vous voulez que les développeurs macOS / Linux exécutent le même build
- Vous voulez réduire à terme le nombre de VM Windows dans le cloud
Si vous avez ce genre d’objectifs, il est préférable de rendre visibles dès maintenant les dépendances aux API Windows.
7.3 System.Drawing.Common est un cas particulièrement mal compris
System.Drawing.Common est, à partir de .NET 6, une bibliothèque exclusivement Windows.
Si vous avez du code qui l’utilise pour du traitement d’image ou du rendu de texte, il faut d’abord décider de la direction à prendre.
- Continuer à exploiter sur Windows ?
- Ou vouloir le faire tourner un jour sur Linux / macOS ?
Dans le premier cas, laisser les choses en l’état pour l’instant peut convenir. Dans le second, il faut inclure dès le départ dans le plan de migration un remplacement par des bibliothèques comme SkiaSharp ou ImageSharp.
7.4 Signes typiques révélant un ancrage à Windows
En présence de références ou d’API comme celles-ci, il est plus sûr d’estimer en partant du principe que la migration restera exclusivement Windows, au moins dans un premier temps.
Microsoft.Win32.RegistrySystem.ManagementSystem.Diagnostics.EventLogSystem.ServiceProcessSystem.DirectoryServicesSystem.DrawingDllImport/ P/Invoke- Références COM
AxInterop.*Microsoft.Office.Interop.*
8. La manière de découper les bibliothèques partagées change la difficulté
Pour les solutions de grande taille, il n’est pas exagéré de dire que le succès de la migration se joue sur la façon dont sont découpées les bibliothèques partagées.
8.1 Commencer par classifier
Il est plus simple d’organiser les bibliothèques en les répartissant en trois grandes catégories.
- La logique métier pure / la logique de domaine
- Une couche intermédiaire légèrement dépendante du modèle applicatif
- Une couche étroitement liée à l’UI / au Web / aux API Windows
Parmi ces trois, c’est la catégorie 1 qu’il faut migrer en premier.
- Calculs
- Évaluation de règles
- DTO / contrats
- Services de domaine
- Transformations de données simples
Si l’on parvient à l’extraire proprement, la difficulté chute nettement.
8.2 netstandard2.0 reste un pont valable
Selon les recommandations de Microsoft, pour une bibliothèque partagée devant aussi coexister avec le côté .NET Framework, il est de base d’envisager d’abord .NET Standard 2.0.
Deux points importent ici.
- .NET Framework ne prend pas en charge
.NET Standard 2.1 - Si vous voulez qu’une bibliothèque partagée soit référencée à la fois par l’ancien et le nouveau code, 2.0 tend à être la solution réaliste
8.3 Ce que change le passage à netstandard2.0
| Politique | Ce qui change | Cas adapté | Points de vigilance |
|---|---|---|---|
Conversion en netstandard2.0 |
Facile à référencer à la fois depuis l’ancien et le nouveau code | Logique métier pure, contrats communs, utilitaires | Les API propres à un modèle applicatif ne peuvent pas y figurer |
Multi-target (ex. net48;net10.0) |
Conserve le code commun tout en gérant des différences par environnement | Bibliothèques avec quelques différences d’environnement | Plus de branches conditionnelles et de gestion de build |
Passage direct à net10.0 uniquement |
Le plus propre à long terme | Nouvelles couches ne nécessitant pas de coexistence ancien/nouveau | Ne peut plus être référencé depuis .NET Framework |
8.4 Le mode de compatibilité n’est pas une solution miracle
.NET Standard 2.0 dispose d’un mode de compatibilité permettant de référencer des bibliothèques .NET Framework. Ce n’est toutefois pas une magie qui ferait fonctionner n’importe quoi de façon transparente.
Par exemple, une bibliothèque reposant sur des API propres à un modèle applicatif comme WPF reste tout simplement difficile. Autrement dit, même en parlant de « bibliothèque partagée », il est essentiel de se limiter aux responsabilités réellement partageables.
8.5 Pour les bibliothèques liées à ASP.NET, tout se joue sur la capacité à retirer System.Web
Lors d’une migration incrémentale d’ASP.NET Framework, avoir des bibliothèques partagées accrochées directement à HttpContext.Current ou à System.Web est très pénible.
Les stratégies de base dans ce cas sont l’une des suivantes :
- Repousser la dépendance à
System.Weben dehors de l’interface - Faire recevoir les informations issues de
HttpContextsous forme de DTO - Utiliser des adaptateurs pendant la période de transition
- Si cela reste impossible, retirer la dépendance progressivement via le multi-targeting
8.6 Migrer les bibliothèques en commençant par les feuilles (leaf-first)
Le guide de migration incrémentale d’ASP.NET indique explicitement de faire migrer les bibliothèques de support en postorder depth-first, c’est-à-dire en partant des feuilles.
Ce principe est très efficace bien au-delà du Web, pour des solutions générales aussi.
- Comme les dépendances sont migrées en premier, les couches supérieures deviennent plus lisibles
- Facilite la localisation des problèmes de compatibilité
- Facilite les tests bibliothèque par bibliothèque
9. Faire l’inventaire de NuGet, des dépendances externes et des composants tiers
Bâcler cette étape est ce qui fait le plus mal en fin de migration.
9.1 Les dépendances s’organisent mieux en quatre catégories
- Paquets NuGet publics
- Paquets privés internes / bibliothèques internes
- Références DLL locales
- COM / ActiveX / DLL natives / SDK
Ne regarder que la catégorie 1 ne suffit pas. Ce qui est vraiment dangereux, ce sont les catégories 3 et 4.
9.2 Ce qu’il faut vérifier pour chaque dépendance
Pour chaque dépendance, vérifiez au minimum ce qui suit.
- Cible-t-elle .NET moderne ?
- Prend-elle en charge
PackageReference? - Fonctionne-t-elle correctement en SDK-style ?
- Y a-t-il des contraintes x86 / x64 / ARM64 ?
- Dépend-elle d’outils design-time ou d’extensions Visual Studio ?
- Suppose-t-elle des scripts d’installation ou des transformations de configuration ?
- Le support est-il toujours actif ?
9.3 Estimer à part les composants UI, reporting et design-time tiers
Pour les migrations WinForms / WPF / ASP.NET, ce point pèse lourd.
- Grilles
- Moteurs de reporting
- Composants de génération de PDF
- Composants graphiques
- Bibliothèques UI intégrées au designer
- Wrappers ActiveX
Ces éléments engagent non seulement le runtime mais aussi le support au design time. Une estimation de migration qui ne regarde que « est-ce que ça compile » passera tout simplement à côté.
9.4 Toujours vérifier les DLL natives et la bitness
Même si le projet semblait tourner en AnyCPU à l’époque de .NET Framework, il peut en réalité dépendre de choses comme :
- COM figé en
x86 - ActiveX exclusivement 32 bits
- Une version spécifique du runtime VC++
- Des DLL natives signées
Ce ne sont pas des problèmes qui apparaissent soudainement avec le passage à .NET moderne : ce sont des contraintes qui existaient déjà et qui refont simplement surface. C’est précisément pour cela qu’il vaut la peine de les rendre visibles avant la migration.
10. Traiter EF6, les sérialiseurs et le domaine des données comme des problèmes distincts
La migration du runtime et la refonte de l’accès aux données ou de la sérialisation fonctionnent mieux lorsqu’elles sont traitées comme des problèmes distincts, autant que possible.
10.1 EF6 → EF Core n’est pas une mise à niveau directe
Le guide EF de Microsoft indique lui aussi qu’EF Core est une réécriture totale d’EF6, sans chemin de mise à niveau direct.
Pour une application utilisant EF6, l’ordre suivant est donc réaliste :
- D’abord passer à .NET moderne
- Faire tourner l’application en conservant EF6 si nécessaire
- Migrer ensuite vers EF Core dans le cadre d’un projet séparé
Ne pas combiner la migration du runtime et la migration de l’ORM. Cela suffit déjà à réduire considérablement la difficulté.
10.2 Ce que change le fait de conserver EF6
- Avantages
- L’écart au niveau de la couche d’accès aux données peut être reporté
- Permet de se concentrer sur la migration de la logique métier et du modèle applicatif
- Les « différences de comportement d’EF Core » n’interfèrent pas
- Points de vigilance
- Pour les nouveaux développements, EF Core reste la solution à privilégier
- L’usage du Designer EF6 / d’EDMX comporte des contraintes spécifiques
10.3 Pour EF6 basé sur EDMX, regarder jusqu’au « design time »
La documentation d’EF6 précise que le EF Designer n’est pas directement pris en charge dans les projets .NET / .NET Standard ni dans les projets .NET Framework au format SDK-style.
Pour une application basée sur EDMX, il faut distinguer ces trois points :
- Fonctionne-t-elle à l’exécution ?
- Le Designer est-il utilisable ?
- Comment gérer le code généré ?
Si vous utilisez EDMX de façon intensive, il est plus sûr d’inclure ce point dans l’estimation dès le départ.
10.4 BinaryFormatter et les sérialisations maison deviennent facilement des « dépendances cachées »
Les sérialiseurs sont faciles à manquer avec une simple recherche dans le code.
- Formats de persistance
- Messagerie
- Cache
- Anciens contrats WCF / SOAP
- ResX
- Presse-papiers / glisser-déposer
Ce domaine engage aussi la compatibilité des données. Autrement dit, il ne suffit pas de vérifier « est-ce que ça build », il faut aussi vérifier si les anciennes données peuvent encore être lues.
11. Inclure la configuration, la distribution, l’exploitation et la CI/CD dans le périmètre de la migration
Le périmètre de la migration ne se limite pas au code source.
11.1 Fichiers de configuration
Côté .NET Framework, app.config / web.config peuvent porter un nombre considérable d’éléments.
- Chaînes de connexion
- Sections de configuration personnalisées
- Configuration des endpoints WCF
- Redirections de binding
- Diagnostics
- Divers réglages ASP.NET
- Résultats des transformations appliquées à l’installation des paquets
Côté .NET moderne, la façon de stocker et de charger la configuration change dans certains cas. « La configuration, on verra plus tard » est donc dangereux.
La première chose à faire est l’inventaire de la configuration.
- Ce qui se trouve dans les fichiers de configuration
- Ce qui est indispensable au démarrage de l’application
- Ce qui relève de différences d’environnement
- Ce qui a été injecté automatiquement par NuGet ou un installateur
11.2 Mode de distribution
Examinez aussi la forme de distribution avant de commencer.
- Sous IIS ?
- Un service Windows ?
- Une tâche planifiée ?
- ClickOnce / MSI / un installateur maison ?
- Suppose-t-il des serveurs on-premise ?
- Self-contained ou framework-dependent, lequel convient le mieux ?
Même si l’exécutable lui-même migre correctement, vous vous retrouverez bloqué en fin de parcours si le mécanisme de distribution et de démarrage repose encore sur d’anciennes hypothèses.
11.3 Journalisation, supervision et procédures d’exploitation
Le volet exploitation est également facile à négliger.
- Suppose-t-il le journal d’événements Windows ?
- Des compteurs de performance sont-ils surveillés ?
- Une supervision basée sur WMI ?
- Les comptes de service et les privilèges sont-ils figés ?
- Les journaux supposent-ils une sortie vers un fichier local ?
Il est tout à fait courant que le code fonctionne après la migration, mais que l’exploitation ne suive plus.
11.4 CI/CD et agents de build
Avant de migrer, vérifiez également ce qui suit.
- Le SDK .NET requis peut-il être installé sur les agents de build ?
- Que faire des pipelines supposant
nuget.exe/msbuild.exe? - Faut-il basculer vers une base CLI
dotnet? - Comment mettre à jour les jobs d’exécution des tests, de couverture de code et de publication ?
- Les modèles internes ou les pipelines réutilisables supposent-ils encore l’ancien format ?
« Ça marche sur mon poste, mais la CI plante » est un grand classique des migrations.
12. Une façon réaliste de mener la migration
En tenant compte de tout ce qui précède, l’approche réaliste se ramène généralement à la forme suivante.
12.1 D’abord mettre de l’ordre côté Framework actuel
- Passer à .NET Framework 4.7.2 ou ultérieur, idéalement 4.8.1
- Mettre à jour les dépendances
- Revoir
packages.config - Basculer vers
PackageReferenceet le format SDK-style dans la mesure du possible - Confirmer que l’application actuelle fonctionne bien dans cet état
Faire seulement cela réduit déjà considérablement l’écart en fin de parcours.
12.2 Sauver d’abord les bibliothèques partagées
Ensuite, rapprochez la logique métier et les contrats communs de netstandard2.0 ou du multi-targeting.
L’ordre de migration suit, en règle générale, le principe leaf-first.
12.3 Adapter la stratégie de l’application elle-même selon le modèle applicatif
- Bibliothèques de classes / console / certains services Relativement simple à mener
- WinForms / WPF Moderniser en restant exclusivement Windows
- ASP.NET MVC / Web API D’un seul coup si petit, par étapes si lourd
- Web Forms Partir du principe d’un remplacement des écrans, en extrayant d’abord la logique partagée
- Serveurs WCF Décider d’abord entre conserver CoreWCF ou refondre en gRPC
12.4 Respecter le principe « ne pas tout faire en même temps »
Les combinaisons à éviter particulièrement sont les suivantes.
- Migration du runtime + remplacement complet de l’ORM
- Migration du runtime + changement de l’infrastructure d’authentification
- Migration du runtime + migration cloud complète
- Migration du runtime + changement de l’infrastructure de supervision
- Migration du runtime + refonte du framework UI
Même si tout est nécessaire, ne pas empiler ces chantiers dans le même sprint fonctionne généralement mieux.
12.5 Prendre des tests et des lignes de base avant d’agir
Voici, au minimum, ce qu’il faut avoir en place avant de bouger :
- Tests unitaires
- Tests d’intégration des principaux flux métier
- Une vérification de type snapshot des écrans / API représentatifs
- Une ligne de base de performance
- Une méthode de vérification des journaux principaux
- Une procédure de retour arrière
Avancer dans un état où l’on ne peut pas identifier « ce qui a cassé » après la migration est particulièrement risqué.
13. Liste de vérification avant de commencer
Voici cette liste sous une forme prête à coller directement dans votre outil de gestion de projet.
13.1 Orientations
- Vous pouvez énoncer en une phrase pourquoi vous migrez
- Le point d’arrivée est décidé : .NET moderne exclusivement Windows ou portabilité multiplateforme à terme
- La version .NET cible est décidée
- Ce qui est exclu du périmètre (passage à EF Core, refonte de l’authentification, migration cloud complète, etc.) est décidé
13.2 Préparation du côté .NET Framework actuel
- Passage à .NET Framework 4.7.2 ou ultérieur, idéalement 4.8.1, effectué
- Dépendances mises à jour vers les versions récentes
- Présence de
packages.configvérifiée - Faisabilité du passage à
PackageReferencevérifiée - Faisabilité du passage au format SDK-style vérifiée
- L’application actuelle build, démarre et passe les tests dans cet état
13.3 Type d’application et choix technologiques
- Difficulté répartie par type : bibliothèque de classes / desktop / Web / WCF, etc.
- Compris que WinForms / WPF resteront exclusivement Windows
- Compris qu’ASP.NET Framework implique une migration du modèle applicatif vers ASP.NET Core
- Remplacement de la couche UI de Web Forms inclus dans l’estimation
- Client et serveur WCF évalués séparément
13.4 Technologies non prises en charge / API à surveiller
- Dépendances à
AppDomainrecensées - Remoting /
MarshalByRefObject/BeginInvoke/EndInvokerecensés - CAS / Security Transparency / COM+ / WF recensés
- Dépendances à BinaryFormatter recensées
- Dépendances à
System.Webrecensées
13.5 Dépendances exclusivement Windows
- Utilisation du registre, de WMI, d’EventLog, des services Windows, de Directory Services recensée
- Utilisation de
System.Drawing.Commonrecensée - COM / ActiveX / Office Interop / P/Invoke / DLL natives recensés
- Contraintes x86 / x64 / ARM64 vérifiées
13.6 Bibliothèques partagées et accès aux données
- Bibliothèques partagées classées entre logique métier et couches étroitement liées au modèle applicatif
- Éléments pouvant passer en
netstandard2.0recensés - Bibliothèques nécessitant du multi-targeting recensées
- Décidé si le runtime peut être migré en premier en conservant EF6
- Dépendances à EDMX / au Designer vérifiées
13.7 Exploitation et build
- Inventaire des fichiers de configuration réalisé
- Mode de distribution vérifié (IIS / service / MSI / ClickOnce, etc.)
- Hypothèses de journalisation / supervision / privilèges / compte d’exécution vérifiées
- Besoin de mise à jour de la CI/CD et des agents de build vérifié
- Procédure de retour arrière rédigée
14. Conclusion
Ce qui compte dans une migration de .NET Framework vers .NET, ce n’est pas tant « avec quelle commande migrer » que de discerner, avant de commencer, ce qui peut passer tel quel et ce qui relève d’un problème à part.
Si l’on devait se limiter à l’essentiel, ce serait ces six points :
- Nettoyer le côté .NET Framework avant de migrer
- Répartir la difficulté selon le modèle applicatif
- Recenser en premier les technologies indisponibles
- Décider jusqu’où accepter une dépendance exclusive à Windows
- Décider comment découper les bibliothèques partagées
- Ne pas empiler ORM, authentification et migration cloud en même temps
La précision de l’estimation d’une migration se joue en grande partie dès la première semaine. Autrement dit, si vous parvenez à clarifier les points en jeu pendant cette semaine, la suite pourra se rapprocher d’un développement assez ordinaire.
« Essayons d’abord de passer à net10.0 » n’est pas une mauvaise idée en phase d’exploration.
Mais pour une migration en production, il y a des points à examiner avant cela. C’est précisément ce que cet article a cherché à clarifier.
15. Références
- Prérequis pour le portage du code
- Vue d’ensemble du portage de .NET Framework vers .NET
- Technologies .NET Framework indisponibles sur .NET 6 et versions ultérieures
- Qu’est-ce que la modernisation d’applications avec GitHub Copilot
- Installer la modernisation d’applications avec GitHub Copilot
- Politique officielle de support de .NET
- Politique officielle de support de .NET Framework
- Utiliser l’outillage pour migrer ASP.NET Framework vers ASP.NET Core
- Migrer d’ASP.NET Framework vers ASP.NET Core
- Démarrer une migration incrémentale d’ASP.NET vers ASP.NET Core
- Utiliser le Windows Compatibility Pack pour porter du code vers .NET
- .NET Standard
- Ciblage multiplateforme pour les bibliothèques .NET
- Migrer de packages.config vers PackageReference
- PackageReference dans les fichiers projet
- Guide de migration de BinaryFormatter
- Guide de migration de BinaryFormatter pour les applications Windows Forms
- Politique de support du client WCF
- Politique de support de CoreWCF
- Pourquoi migrer WCF vers gRPC sur ASP.NET Core
- Porter EF6 vers EF Core
- Nouveautés d’EF6
Articles associés
Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.
Jusqu'à quand les applications VB6 continueront-elles de fonctionner ? — état du support du runtime et démarche concrète vers une migration .NET
Jusqu'à quand les applications VB6 continueront-elles de fonctionner ? Cet article clarifie l'asymétrie entre la politique de support du ...
Versionner le schéma de base de données d'une application métier — pratiques de migration pour éviter que « chaque client ait une base différente »
Guide pratique pour versionner le schéma de base de données d'applications métier dont les bases sont dispersées chez chaque client. Impl...
CI/CD pratique pour les applications WinForms / WPF — Automatiser du build à la signature et à la distribution avec GitHub Actions
Guide pratique pour mettre en place le CI/CD des applications WinForms / WPF avec GitHub Actions. Couvre un YAML minimal de build+tests s...
Quand votre application Windows maison est signalée comme un virus — gérer les faux positifs de Microsoft Defender et composer avec l'impact sur les performances
Nous détaillons la marche à suivre officielle lorsque Microsoft Defender signale à tort une application Windows développée en interne com...
Veille, mise en veille prolongée, Modern Standby et applications longue durée — concevoir pour éviter « ça s'était arrêté pendant la nuit »
Pourquoi une application Windows censée tourner en continu se retrouve « arrêtée quand on la consulte le matin » : différences entre la v...
Sujets associés
Ces pages replacent le sujet dans un contexte plus large de services et de décisions.
Thèmes techniques Windows
Portail des sujets sur le développement Windows, l'analyse des incidents et la valorisation des actifs existants.
Services liés à ce sujet
Cet article est directement lié aux services suivants.
Réutilisation et migration d'actifs existants
Il s'agit de faire l'inventaire d'un patrimoine existant impliquant .NET Framework, Web Forms, WCF, COM / ActiveX et d'anciennes pratiques NuGet, ce qui correspond bien à une consultation sur la migration d'actifs legacy.
Conseil technique et revue de conception
Si vous souhaitez clarifier avant de commencer le périmètre de la migration, la manière de découper une migration par étapes, et jusqu'où accepter une dépendance exclusive à Windows, ce sujet se prête bien à une consultation technique ou une revue de conception.
Questions fréquentes
Questions souvent posées lors d’une consultation sur le sujet de cet article.
- Que dois-je faire avant de migrer de .NET Framework vers .NET ?
- Commencez par nettoyer le côté .NET Framework. Le guide officiel de Microsoft recommande lui aussi, avant le portage, de passer à .NET Framework 4.7.2 ou ultérieur (en pratique 4.8.1 est la base la plus claire), de convertir les références en PackageReference, de basculer vers des projets au format SDK-style et de mettre à jour les dépendances vers les dernières versions disponibles. Faire cela en premier réduit fortement l'écart lors de la phase suivante, et permet de distinguer plus facilement si un problème de compatibilité vient de l'ancienneté du Framework ou du passage à .NET moderne. Confirmez également que l'application actuelle build, démarre et passe les tests dans cet état.
- Quelles technologies de .NET Framework ne fonctionnent pas sur .NET moderne ?
- Les signaux rouges sont la création d'AppDomain (comme AppDomain.CreateDomain), .NET Remoting, Code Access Security, System.EnterpriseServices (COM+), Workflow Foundation, et l'hébergement natif de serveur WCF. BinaryFormatter mérite une attention particulière : à partir de .NET 9, son implémentation lève systématiquement PlatformNotSupportedException, et il se cache dans les données persistées, les caches, le presse-papiers et le glisser-déposer, les ResX, ainsi que la sérialisation du designer WinForms/WPF. Pour les serveurs WCF, les voies possibles sont CoreWCF (un sous-ensemble préservant la compatibilité côté client) ou une refonte autour de gRPC ou d'API HTTP.
- Mon application deviendra-t-elle multiplateforme après une migration vers .NET ?
- Pas automatiquement. WinForms et WPF migrent vers .NET moderne mais restent des frameworks exclusivement Windows, et System.Drawing.Common est une bibliothèque exclusivement Windows à partir de .NET 6. Les dépendances liées à Windows telles que le registre, WMI, EventLog, les services Windows, COM, Office Interop et P/Invoke vous suivent après la migration. Migrer en restant exclusivement Windows est tout à fait réaliste — le Windows Compatibility Pack existe précisément pour cela — mais si les conteneurs Linux sont un objectif futur, il faut inventorier tôt ces API liées à Windows et prévoir des remplacements comme SkiaSharp ou ImageSharp pour le code d'imagerie.
- Faut-il migrer EF6 vers EF Core en même temps que la migration du runtime ?
- Non. EF Core est une réécriture totale d'EF6, sans chemin de mise à niveau direct, donc combiner la migration de l'ORM avec la migration du runtime augmente nettement la difficulté. L'ordre réaliste consiste à passer d'abord à .NET moderne, à conserver EF6 si nécessaire, puis à migrer vers EF Core dans le cadre d'un projet séparé. Le même principe s'applique plus largement : évitez d'empiler la migration du runtime avec un changement d'authentification, une migration cloud, un changement de supervision ou une refonte du framework UI dans le même effort, même si tout cela finit par être nécessaire.
Profil de l’auteur
Page de présentation de l’auteur de l’article.
Go Komura
Représentant de KomuraSoft LLC
Spécialisé dans le développement de logiciels Windows, le conseil technique et l’analyse de pannes, notamment pour les systèmes existants et les incidents difficiles à reproduire.
Liens publics