Migration et données

Migrer une application ASP.NET Web Forms vers ASP.NET Core : la méthode progressive

Migration et données · · Publié le 2026-11-10

Beaucoup d'intranets, d'extranets métier et d'applications de gestion tournent encore sous ASP.NET Web Forms, souvent écrits il y a quinze ans et maintenus par une équipe réduite. Ils fonctionnent, mais ils sont liés à .NET Framework et à Windows Server. Passer à ASP.NET Core n'est pas une mise à jour : c'est une réécriture de la couche web. Bien conduite, elle peut pourtant se faire page par page, sans « grand soir ».

Faut-il vraiment migrer, et quand ?

Commençons par dissiper un malentendu. .NET Framework 4.8 et 4.8.1 n'ont pas de date de fin de support annoncée : Microsoft les traite comme des composants de Windows, pris en charge tant que la version de Windows qui les héberge l'est (voir la fiche de cycle de vie de .NET Framework). Une application Web Forms à jour de ses correctifs n'est donc pas, en soi, une faille béante.

Les raisons de migrer sont ailleurs : Web Forms ne reçoit plus de nouveautés, les bibliothèques tierces abandonnent .NET Framework les unes après les autres, l'hébergement est limité à IIS sous Windows, et il devient difficile de recruter des développeurs qui veulent travailler sur du ViewState. Côté cible, la version à viser aujourd'hui est .NET 10, version à support long (LTS) sortie le 11 novembre 2025 et prise en charge jusqu'au 14 novembre 2028 ; .NET 8 et .NET 9 arrivent tous deux en fin de support le 10 novembre 2026, selon la politique de support de .NET.

Ce qui ne passe pas d'un monde à l'autre

ASP.NET Core n'embarque pas l'assembly System.Web. Tout ce qui en dépend doit être remplacé :

Choisir la cible : Razor Pages, MVC ou Blazor

Pour une application organisée en pages et formulaires, Razor Pages est souvent le choix le plus naturel : un fichier .cshtml et sa classe PageModel jouent un rôle proche du couple .aspx et code-behind, sans ViewState. MVC convient mieux quand l'application expose aussi une API ou que l'équipe le pratique déjà.

Blazor, enfin, est le modèle dont la logique ressemble le plus à Web Forms : des composants réutilisables, des gestionnaires d'événements écrits en C#, un état conservé entre deux interactions. Microsoft a d'ailleurs publié un livre gratuit, Blazor pour les développeurs ASP.NET Web Forms, qui fait correspondre les notions une à une. Attention cependant à ne pas reproduire l'architecture d'origine par réflexe : en mode serveur interactif, chaque utilisateur maintient une connexion permanente, ce qui change la façon de dimensionner les serveurs.

Rien n'oblige à choisir un seul modèle : une même application ASP.NET Core peut servir des Razor Pages pour les écrans de saisie classiques et des composants Blazor pour un tableau de bord.

La méthode progressive : un proxy devant l'ancienne application

Pour une application de production, Microsoft recommande une migration incrémentale, inspirée du motif dit du « figuier étrangleur » : une nouvelle application ASP.NET Core est placée devant l'ancienne et reçoit toutes les requêtes. Celles qu'elle sait traiter, elle les traite ; les autres, elle les transmet à l'application Web Forms grâce au proxy inverse YARP. On déplace ensuite les écrans un par un, et l'ancienne application rétrécit jusqu'à disparaître. La démarche est décrite dans le guide Prise en main de la migration incrémentielle.

Le cœur de la configuration tient en quelques lignes. Le point important est la route « attrape-tout », placée en dernier, qui renvoie vers l'ancienne application tout ce qui n'a pas encore été migré :

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddSystemWebAdapters();   // paquet Microsoft.AspNetCore.SystemWebAdapters
builder.Services.AddHttpForwarder();       // YARP

var app = builder.Build();

app.UseRouting();
app.UseSystemWebAdapters();
app.MapRazorPages();                       // les écrans déjà migrés

// Tout le reste part vers l'application Web Forms d'origine
app.MapForwarder("/{**catch-all}", app.Configuration["AncienneAppUrl"]!)
   .Add(static b => ((RouteEndpointBuilder)b).Order = int.MaxValue);

app.Run();

La documentation de configuration de l'application distante détaille la partie enregistrée côté .NET Framework, notamment la clé partagée qui authentifie les échanges entre les deux applications.

Partager la session et l'authentification pendant la transition

Le principal obstacle d'une migration progressive est l'état partagé. Si l'utilisateur se connecte sur une page Web Forms puis arrive sur une page Razor, il doit rester connecté ; si son panier est en session, il doit le retrouver. Les adaptateurs System.Web proposent pour cela une session distante et une authentification distante : la nouvelle application interroge l'ancienne, qui reste la source de vérité. Les détails sont dans les pages consacrées à la session et à l'authentification.

Deux conditions pratiques en découlent : tout ce qui est placé en session doit être sérialisable (fini les objets DataTable ou les connexions stockées « pour gagner du temps »), et il faut déclarer explicitement quelles clés de session sont partagées et avec quel type.

Les bibliothèques d'abord, des feuilles vers le tronc

La logique métier qui vit dans des bibliothèques de classes doit pouvoir servir aux deux applications pendant la transition. Le guide de Microsoft recommande de les faire cibler .NET Standard 2.0 quand c'est possible, sinon de les compiler à la fois pour .NET Framework et pour .NET 8 ou ultérieur, et de les mettre à niveau dans l'ordre des dépendances : d'abord celles qui ne dépendent d'aucune autre, l'application web en dernier. Une bibliothèque qui utilise HttpContext.Current peut remplacer sa référence à System.Web par le paquet des adaptateurs, ce qui évite de la réécrire immédiatement.

Avant même ce travail, deux chantiers préparatoires rapportent beaucoup : convertir les projets au format « SDK » et passer de packages.config à PackageReference, puis éliminer le code mort et les avertissements de compilation sur les API obsolètes.

Faire l'inventaire avant d'écrire une ligne

Une migration réussie commence par une liste. Pour chaque page .aspx, notez : les contrôles tiers utilisés (une suite de composants commerciale sans équivalent récent peut à elle seule imposer une refonte d'écran), les sources de données (SqlDataSource déclaratif, ADO.NET, procédures stockées), l'usage de la session et du cache, les droits d'accès, et la fréquentation réelle d'après les journaux IIS. Les écrans peu consultés et simples sont de bons candidats pour roder la chaîne ; les écrans critiques viennent ensuite, quand l'équipe maîtrise le nouvel environnement.

Pour la couche de données, c'est le moment de décider si l'on conserve ADO.NET (qui fonctionne très bien sous .NET 10 avec Microsoft.Data.SqlClient) ou si l'on adopte Entity Framework Core, sujet de notre article Entity Framework Core pour les développeurs ADO.NET.

Pièges fréquents dans une application française

En résumé

Placez une application ASP.NET Core devant l'existant, faites-lui transmettre par défaut toutes les requêtes à Web Forms, partagez session et authentification, puis migrez écran par écran en commençant par les plus simples. Chaque étape est livrable, réversible et testable en production réelle. C'est plus long sur le papier qu'une réécriture complète ; dans les faits, c'est presque toujours la seule qui aboutit.

Documentation officielle