Why wait for .NET 10 to migrate?
I had been looking forward to this release, mainly because of a Blazor Server reconnection bug I reported myself : https://github.com/dotnet/aspnetcore/issues/64228 . This issue affected the reliability of automatic reconnection after a network drop, and it was a real problem for a B2B application used continuously throughout the day. The fix is finally included in .NET 10, which made the migration even more worthwhile.
1. Update the .csproj
First step, no surprise here: update the target framework in the project file.
<TargetFramework>net10.0</TargetFramework>XMLThis is the mandatory starting point before any other change.
2. Update NuGet packages
Once the framework is updated, all packages need to follow. I updated the Microsoft dependencies (Microsoft.AspNetCore.*, etc.) to their 10.x versions, along with any third-party packages compatible with .NET 10. It is also a good opportunity to check for incompatibilities and clean up obsolete dependencies.
3. New Blazor structure files
This is where .NET 10 brings the most structural changes. I created a blank Blazor Server template project to extract the updated files.
NotFound.razor
A dedicated 404 page is now part of the default template. It is registered directly in Routes.razor via the new NotFoundPage attribute:
<Router AppAssembly="typeof(App).Assembly"
NotFoundPage="typeof(Pages.NotFound)" />RazorNo more inline <NotFound> block inside the router, which makes things cleaner and better separated.
ReconnectModal: reconnection rethought
The reconnection handling has also changed: it is now encapsulated in three dedicated files:
ReconnectModal.razorfor the UI componentReconnectModal.razor.csfor the code-behindReconnectModal.razor.jsfor the client-side reconnection logic
This component goes into the <body> of App.razor:
<body>
...
<ReconnectModal />
<Routes />
</body>Razori18n bonus: I took the opportunity to customize ReconnectModal.razor.js to handle automatic translation of the reconnection messages. The code is available on my GitHub: tossnet/Blazor-Reconnect-demo-i18n
4. The Blazor script becomes a static asset
A notable change in App.razor: the Blazor script now goes through the static asset system. You use @Assets[] instead:
<script src="@Assets["_framework/blazor.web.js"]"></script>RazorThis lets the framework handle cache-busting automatically through a fingerprint on the file name.
5. ResourcePreloader in the <head>
One last thing not to forget: the <ResourcePreloader /> component to add in the <head>:
<head>
...
<ResourcePreloader />
</head>RazorIt injects the appropriate <link rel="preload"> tags for static assets, which improves performance on the initial load.
Summary of changes
- Update
<TargetFramework>net10.0</TargetFramework>in the.csproj - Update NuGet packages to .NET 10 compatible versions
- Grab
NotFound.razor,ReconnectModal.razor,.razor.csand.razor.jsfrom a template project - Add
NotFoundPage="typeof(Pages.NotFound)"on<Router />inRoutes.razor - Replace the Blazor script with
<script src="@Assets["_framework/blazor.web.js"]"></script> - Add
<ReconnectModal />in the<body>and<ResourcePreloader />in the<head>
Going further
I recorded a DevApps episode (in French) covering all the Blazor .NET 10 new features: watch it on YouTube.
The migration is fairly smooth overall. The biggest change is the restructuring of the reconnection handling and static assets, which is also a good opportunity to tailor the behavior to your needs.
