Events
Power BI DataViz World Championships
Feb 14, 4 PM - Mar 31, 4 PM
With 4 chances to enter, you could win a conference package and make it to the LIVE Grand Finale in Las Vegas
Learn moreThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
This article explains how to update an existing ASP.NET Core 3.1 project to ASP.NET Core 5.0. For instructions on how to migrate from ASP.NET Core 3.1 to ASP.NET Core 6.0, see Migrate from ASP.NET Core 3.1 to 6.0.
If you rely upon a global.json file to target a specific .NET Core SDK version, update the version
property to the .NET 5.0 SDK version that's installed. For example:
{
"sdk": {
- "version": "3.1.200"
+ "version": "5.0.100"
}
}
If updating a Blazor WebAssembly project, skip to the Update Blazor WebAssembly projects section. For any other ASP.NET Core project type, update the project file's Target Framework Moniker (TFM) to net5.0
:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
- <TargetFramework>netcoreapp3.1</TargetFramework>
+ <TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>
You may need to delete the bin
and obj
folders. Run dotnet nuget locals --clear all
to clear the NuGet package cache.
The computation of route precedence changed in the ASP.NET Core 5.0.1 patch release. This might affect you if you've defined catch-all routes or routes with optional parameters.
With the prior behavior in ASP.NET Core 5.0.0 or earlier, routes with lower precedence, such as {*slug}
, are matched before routes with higher precedence, such as /customer/{id}
.
The new behavior in ASP.NET Core 5.0.1 or later more closely matches the routing behavior defined in ASP.NET Core apps, where the framework computes and establishes the route precedence for each segment first and only uses the length of the route to break ties as a secondary criteria.
The original behavior is considered a bug in the implementation because our goal is for the Blazor routing system to behave in the same way as the ASP.NET Core routing system for the subset of features supported by Blazor routing.
Add the PreferExactMatches
attribute to the Router
component in the App.razor
file to opt into the correct behavior:
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
When PreferExactMatches
is set to @true
, route matching prefers exact matches over wildcards.
Important
All apps should explicitly set PreferExactMatches
to @true
.
The ability to set PreferExactMatches
to @false
or leave it unset is only provided for backward compatibility.
When .NET 6 is released, the router will always prefer exact matches, and the PreferExactMatches
option won't be available.
The guidance in this section applies to both Blazor hosting models. Sections following this section provide additional guidance specific to hosting models and app types. Apply the guidance from all relevant sections to your app.
In wwwroot/index.html
of a Blazor WebAssembly app or the Pages/_Host.cshtml
of a Blazor Server app, add a <link>
element to the <head>
element for styles. In the following <link>
element href
attribute values, the placeholder {ASSEMBLY NAME}
is the app's assembly name.
+<link href="{ASSEMBLY NAME}.styles.css" rel="stylesheet" />
Standalone Blazor WebAssembly or Blazor Server example:
+<link href="BlazorSample.styles.css" rel="stylesheet" />
Client
project of a hosted Blazor WebAssembly solution example:
+<link href="BlazorSample.Client.styles.css" rel="stylesheet" />
Include a new namespace in the app's _Imports.razor
file for component virtualization, Microsoft.AspNetCore.Components.Web.Virtualization. The following _Imports.razor
files show the default namespaces in apps generated from the Blazor project templates. The placeholder {ASSEMBLY NAME}
is the app's assembly name.
Blazor WebAssembly (_Imports.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 {ASSEMBLY NAME}
@using {ASSEMBLY NAME}.Shared
Blazor Server (_Imports.razor
):
@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using {ASSEMBLY NAME}
@using {ASSEMBLY NAME}.Shared
In the MainLayout
component (Shared/MainLayout.razor
), surround the component's HTML markup with a <div>
element that has a class
attribute set to page
:
<div class="page">
...
</div>
Add the following files to the Shared
folder:
MainLayout.razor.css
:
.page {
position: relative;
display: flex;
flex-direction: column;
}
.main {
flex: 1;
}
.sidebar {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}
.top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
height: 3.5rem;
display: flex;
align-items: center;
}
.top-row ::deep a, .top-row .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
}
.top-row a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}
@media (max-width: 767.98px) {
.top-row:not(.auth) {
display: none;
}
.top-row.auth {
justify-content: space-between;
}
.top-row a, .top-row .btn-link {
margin-left: 0;
}
}
@media (min-width: 768px) {
.page {
flex-direction: row;
}
.sidebar {
width: 250px;
height: 100vh;
position: sticky;
top: 0;
}
.top-row {
position: sticky;
top: 0;
z-index: 1;
}
.main > div {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
}
}
NavMenu.razor.css
:
.navbar-toggler {
background-color: rgba(255, 255, 255, 0.1);
}
.top-row {
height: 3.5rem;
background-color: rgba(0,0,0,0.4);
}
.navbar-brand {
font-size: 1.1rem;
}
.oi {
width: 2rem;
font-size: 1.1rem;
vertical-align: text-top;
top: -2px;
}
.nav-item {
font-size: 0.9rem;
padding-bottom: 0.5rem;
}
.nav-item:first-of-type {
padding-top: 1rem;
}
.nav-item:last-of-type {
padding-bottom: 1rem;
}
.nav-item ::deep a {
color: #d7d7d7;
border-radius: 4px;
height: 3rem;
display: flex;
align-items: center;
line-height: 3rem;
}
.nav-item ::deep a.active {
background-color: rgba(255,255,255,0.25);
color: white;
}
.nav-item ::deep a:hover {
background-color: rgba(255,255,255,0.1);
color: white;
}
@media (min-width: 768px) {
.navbar-toggler {
display: none;
}
.collapse {
/* Never collapse the sidebar for wide screens */
display: block;
}
}
The latest base wwwroot/css/app.css
file of a Blazor WebAssembly app or wwwroot/css/site.css
file of a Blazor Server app includes the following styles. Remove extra styles leaving the following styles and any that you've added to the app.
The following stylesheet only includes base styles and does not include custom styles added by the developer:
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
a, .btn-link {
color: #0366d6;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.content {
padding-top: 1.1rem;
}
.valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050;
}
.invalid {
outline: 1px solid red;
}
.validation-message {
color: red;
}
#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
Note
The preceding example doesn't show the @import
directive for Open Iconic icons (open-iconic-bootstrap.css
), provided by the Blazor project template. Open Iconic was abandoned by its maintainers.
Follow the guidance in the preceding Update Blazor WebAssembly and Blazor Server projects section.
For a Blazor WebAssembly project, including the Client
project of a hosted Blazor solution, apply the following changes to the project file:
Update the SDK from Microsoft.NET.Sdk.Web
to Microsoft.NET.Sdk.BlazorWebAssembly
:
- <Project Sdk="Microsoft.NET.Sdk.Web">
+ <Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
Note
This update only applies to standalone Blazor WebAssembly projects and the Client
projects of hosted Blazor solutions.
Update the following properties:
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
- <TargetFramework>netstandard2.1</TargetFramework>
- <RazorLangVersion>3.0</RazorLangVersion>
+ <TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
Remove the package reference to Microsoft.AspNetCore.Components.WebAssembly.Build:
<ItemGroup>
- <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="3.2.1" PrivateAssets="all" />
Update other packages to their latest versions. The latest versions can be found at NuGet.org.
In wwwroot/index.html
, change the element that loads the App
component to a <div>
element with an id
set to app
:
-<app>Loading...</app>
+<div id="app">Loading...</div>
In Program.Main
(Program.cs
), change the reference to the <app>
element to a CSS selector by adding a hash #
to it:
-builder.RootComponents.Add<App>("app");
+builder.RootComponents.Add<App>("#app");
In Program.Main
(Program.cs
), change a default transient HttpClient
registration to scoped, if present:
-builder.Services.AddTransient(sp => new HttpClient
- { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
+builder.Services.AddScoped(sp => new HttpClient
+ { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
In Program.Main
(Program.cs
) of the Client
app of hosted Blazor solutions:
builder.HostEnvironment.BaseAddress
for string client base addresses.-builder.Services.AddHttpClient("{APP NAMESPACE}.ServerAPI",
- client => client.BaseAddress = new Uri("https://localhost:5001"))
- .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
-builder.Services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory>()
- .CreateClient("{APP NAMESPACE}.ServerAPI"));
+builder.Services.AddHttpClient("{APP NAMESPACE}.ServerAPI",
+ client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
+ .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
+builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
+ .CreateClient("{APP NAMESPACE}.ServerAPI"));
In the preceding code, the {APP NAMESPACE}
placeholder is the app's namespace.
Follow the guidance in the preceding Update Blazor WebAssembly and Blazor Server projects and Update Blazor WebAssembly projects sections.
For a standalone Blazor WebAssembly app registered in the Azure portal to use Microsoft Entra ID (ME-ID) for Microsoft Accounts:
The app requires the openid
and offline_access
scopes:
options.ProviderOptions.DefaultAccessTokenScopes.Add("openid");
options.ProviderOptions.DefaultAccessTokenScopes.Add("offline_access");
In the Azure portal app registration Authentication blade:
For more information, see Secure an ASP.NET Core Blazor WebAssembly standalone app with Microsoft Accounts.
Follow the guidance in the preceding Update Blazor WebAssembly and Blazor Server projects and Update Blazor WebAssembly projects sections.
For a standalone Blazor WebAssembly app registered in the Azure portal to use Microsoft Entra ID (ME-ID):
The app requires the https://graph.microsoft.com/User.Read
scope:
options.ProviderOptions.DefaultAccessTokenScopes
.Add("https://graph.microsoft.com/User.Read");
In the Azure portal app registration Authentication blade:
For more information, see Secure an ASP.NET Core Blazor WebAssembly standalone app with Microsoft Entra ID.
Follow the guidance in the preceding Update Blazor WebAssembly and Blazor Server projects and Update Blazor WebAssembly projects sections.
For a standalone Blazor WebAssembly app registered in the Azure portal to use Azure Active Directory (AAD) B2C:
The app requires the openid
and offline_access
scopes:
options.ProviderOptions.DefaultAccessTokenScopes.Add("openid");
options.ProviderOptions.DefaultAccessTokenScopes.Add("offline_access");
In the Azure portal app registration Authentication blade:
For more information, see Secure an ASP.NET Core Blazor WebAssembly standalone app with Azure Active Directory B2C.
Follow the guidance in the preceding Update Blazor WebAssembly and Blazor Server projects and Update Blazor WebAssembly projects sections.
The Client
app registration of a hosted Blazor solution that uses AAD or AAD B2C for user authentication should use a Single-page application Azure Apps platform configuration.
In the Azure portal Client
app registration Authentication blade:
For more information, see:
Follow the guidance in the preceding sections:
Update the Server
project of a hosted Blazor solution as an ASP.NET Core app following the general guidance in this article.
Additionally, Server
projects that authenticate users to client Blazor WebAssembly apps with Microsoft Entra ID (ME-ID) or B2C should adopt new Microsoft Identity v2.0 packages:
For AAD:
-<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="..." />
+<PackageReference Include="Microsoft.Identity.Web" Version="{VERSION}" />
+<PackageReference Include="Microsoft.Identity.Web.UI" Version="{VERSION}" />
For AAD B2C:
-<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" Version="..." />
+<PackageReference Include="Microsoft.Identity.Web" Version="{VERSION}" />
+<PackageReference Include="Microsoft.Identity.Web.UI" Version="{VERSION}" />
For the preceding package references, determine the package versions for the {VERSION}
placeholders at NuGet.org:
Note
The SDK of the Server
project in a hosted Blazor WebAssembly solution remains Microsoft.NET.Sdk.Web
:
<Project Sdk="Microsoft.NET.Sdk.Web">
For more information, see:
After migrating the app or solution to .NET 5, clean and rebuild the app or solution. If package incompatibilities exist between new package references and cached packages:
Clear NuGet package caches by executing the following dotnet nuget locals
command in a command shell:
dotnet nuget locals --clear all
Clean and rebuild the app or solution.
Follow the Troubleshoot guidance at the end of the Blazor WebAssembly security topic that applies to your app:
Standalone Blazor WebAssembly apps:
Hosted Blazor WebAssembly apps:
After upgrading a Blazor WebAssembly app that uses AAD for authentication, you may receive the following error on the login callback to the app after the user signs in with AAD:
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Authorization failed. These requirements were not met: DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
Login callback error from AAD:
unauthorized_client
AADB2C90058: The provided application is not configured to allow public clients.
To resolve the error:
allowPublicClient
attribute to null
or true
.Add the following item to the PWA app's project file:
<ItemGroup>
<ServiceWorker Include="wwwroot\service-worker.js"
PublishedContent="wwwroot\service-worker.published.js" />
</ItemGroup>
If the project's wwwroot/index.html
(Blazor WebAssembly) or Pages/_Host.cshtml
(Blazor Server) contains a stylesheet <link>
element for scoped.styles.css
from an earlier 5.0 preview release, remove the <link>
tag:
-<link href="_framework/scoped.styles.css/" rel="stylesheet" />
Migrate Razor class libraries (RCLs) to take advantage of new APIs or features that are introduced as part of ASP.NET Core 5.0.
To update a RCL that targets components:
Update the following properties in the project file:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
- <TargetFramework>netstandard2.0</TargetFramework>
- <RazorLangVersion>3.0</RazorLangVersion>
+ <TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
Update other packages to their latest versions. The latest versions can be found at NuGet.org.
To update an RCL targeting MVC, update the following properties in the project file:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
- <TargetFramework>netcoreapp3.1</TargetFramework>
+ <TargetFramework>net5.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
In the project file, update each Microsoft.AspNetCore.*, Microsoft.EntityFrameworkCore.*, Microsoft.Extensions.*, and System.Net.Http.Json package reference's Version
attribute to 5.0.0 or later. For example:
<ItemGroup>
- <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="3.1.6" />
- <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.6">
- <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.6" />
- <PackageReference Include="System.Net.Http.Json" Version="3.2.1" />
+ <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="5.0.0" />
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0">
+ <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0" />
+ <PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
</ItemGroup>
For apps using Docker, update your Dockerfile FROM
statements and scripts. Use a base image that includes the ASP.NET Core 5.0 runtime. Consider the following docker pull
command difference between ASP.NET Core 3.1 and 5.0:
- docker pull mcr.microsoft.com/dotnet/core/aspnet:3.1
+ docker pull mcr.microsoft.com/dotnet/aspnet:5.0
As part of the move to ".NET" as the product name, the Docker images moved from the mcr.microsoft.com/dotnet/core
repositories to mcr.microsoft.com/dotnet
. For more information, see dotnet/dotnet-docker#1939.
In ASP.NET Core 3.1 and earlier, DateTime
values were model-bound as local time, where the timezone was determined by the server. DateTime
values bound from input formatting (JSON) and DateTimeOffset
values were bound as UTC timezones.
In ASP.NET Core 5.0 and later, model binding consistently binds DateTime
values with the UTC timezone.
To retain the previous behavior, remove the DateTimeModelBinderProvider
in Startup.ConfigureServices
:
services.AddControllersWithViews(options =>
options.ModelBinderProviders.RemoveType<DateTimeModelBinderProvider>());
To add support for model binding C# 9 record types, the ComplexTypeModelBinderProvider is:
Apps that rely on the presence of the ComplexTypeModelBinderProvider
in the ModelBinderProviders
collection need to reference the new binder provider:
- var complexModelBinderProvider = options.ModelBinderProviders.OfType<ComplexTypeModelBinderProvider>();
+ var complexModelBinderProvider = options.ModelBinderProviders.OfType<ComplexObjectModelBinderProvider>();
The ASP.NET Core 3.1 templates that include an option for individual user accounts generate a call to UseDatabaseErrorPage. UseDatabaseErrorPage
is now obsolete and should be replaced with a combination of AddDatabaseDeveloperPageExceptionFilter
and UseMigrationsEndPoint
, as shown in the following code:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
+ services.AddDatabaseDeveloperPageExceptionFilter();
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
+ app.UseMigrationsEndPoint();
- app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
For more information, see this GitHub issue.
If the ASP.NET Core Module (ANCM) wasn't a selected component when Visual Studio was installed or if a prior version of the ANCM was installed on the system, download the latest .NET Core Hosting Bundle Installer (direct download) and run the installer. For more information, see Hosting Bundle.
With the migration of some Microsoft.Extensions.*
NuGet packages from the dotnet/extensions repository to dotnet/runtime, as described in Migrating dotnet/extensions content to dotnet/runtime and dotnet/aspnetcore (aspnet/Announcements #411), packaging changes are being applied to some of the migrated packages. These changes often result in namespace changes for .NET API.
To research APIs further for app namespace changes when migrating to 5.0, use the .NET API browser.
The following wiki pages explain how to migrate Microsoft.Identity.Web from ASP.NET Core 3.1 to 5.0:
The following tutorials also explain the migration:
For breaking changes from .NET Core 3.1 to .NET 5.0, see Breaking changes for migration from version 3.1 to 5.0. ASP.NET Core and Entity Framework Core are also included in the list.
ASP.NET Core feedback
ASP.NET Core is an open source project. Select a link to provide feedback:
Events
Power BI DataViz World Championships
Feb 14, 4 PM - Mar 31, 4 PM
With 4 chances to enter, you could win a conference package and make it to the LIVE Grand Finale in Las Vegas
Learn moreTraining
Module
ASP.NET Core Identity フレームワークを使用して .NET Web アプリをセキュリティで保護する - Training
ASP.NET Core Identity フレームワークを使用して、.NET Web アプリに認証と認可を追加する方法について説明します。
Certification
Microsoft Certified: Identity and Access Administrator Associate - Certifications
ID ソリューションの現代化、ハイブリッド ソリューションの実装、ID ガバナンスの実装を行う Microsoft Entra ID の機能を実証します。