Training
Module
Secure a .NET web app with the ASP.NET Core Identity framework - Training
Learn how to add authentication and authorization to a .NET web app using the ASP.NET Core Identity framework.
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
If you're migrating to version 3.0 of .NET Core, ASP.NET Core, or EF Core, the breaking changes listed in this article may affect your app.
Obsolete members and compatibility switches in ASP.NET Core 2.2 were removed.
3.0
Improvement of API surface over time.
While targeting .NET Core 2.2, follow the guidance in the obsolete build messages to adopt new APIs instead.
ASP.NET Core
The following types and members were marked as obsolete for ASP.NET Core 2.1 and 2.2:
Types
Microsoft.AspNetCore.Diagnostics.Views.WelcomePage
Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue
Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView
Microsoft.AspNetCore.DiagnosticsViewPage.Views.HelperResult
Microsoft.AspNetCore.Mvc.Formatters.Xml.ProblemDetails21Wrapper
Microsoft.AspNetCore.Mvc.Formatters.Xml.ValidationProblemDetails21Wrapper
Microsoft.AspNetCore.Mvc.Razor.Compilation.ViewsFeatureProvider
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageArgumentBinder
Microsoft.AspNetCore.Routing.IRouteValuesAddressMetadata
Microsoft.AspNetCore.Routing.RouteValuesAddressMetadata
Constructors
Microsoft.AspNetCore.Cors.Infrastructure.CorsService(IOptions{CorsOptions})
Microsoft.AspNetCore.Routing.Tree.TreeRouteBuilder(ILoggerFactory,UrlEncoder,ObjectPool{UriBuildingContext},IInlineConstraintResolver)
Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext
Microsoft.AspNetCore.Mvc.ApiExplorer.DefaultApiDescriptionProvider(IOptions{MvcOptions},IInlineConstraintResolver,IModelMetadataProvider)
Microsoft.AspNetCore.Mvc.ApiExplorer.DefaultApiDescriptionProvider(IOptions{MvcOptions},IInlineConstraintResolver,IModelMetadataProvider,IActionResultTypeMapper)
Microsoft.AspNetCore.Mvc.Formatters.FormatFilter(IOptions{MvcOptions})
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ArrayModelBinder`1(IModelBinder)
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ByteArrayModelBinder
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DictionaryModelBinder`2(IModelBinder,IModelBinder)
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DoubleModelBinder(System.Globalization.NumberStyles)
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FloatModelBinder(System.Globalization.NumberStyles)
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormCollectionModelBinder
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormFileModelBinder
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.HeaderModelBinder
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.KeyValuePairModelBinder`2(IModelBinder,IModelBinder)
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder(System.Type)
Microsoft.AspNetCore.Mvc.ModelBinding.ModelAttributes(IEnumerable{System.Object})
Microsoft.AspNetCore.Mvc.ModelBinding.ModelAttributes(IEnumerable{System.Object},IEnumerable{System.Object})
Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactory(IModelMetadataProvider,IOptions{MvcOptions})
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder(IModelMetadataProvider,IModelBinderFactory,IObjectModelValidator)
Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerInputFormatter
Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerInputFormatter(System.Boolean)
Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerInputFormatter(MvcOptions)
Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter
Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter(System.Boolean)
Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter(MvcOptions)
Microsoft.AspNetCore.Mvc.TagHelpers.LinkTagHelper(IHostingEnvironment,IMemoryCache,HtmlEncoder,JavaScriptEncoder,IUrlHelperFactory)
Microsoft.AspNetCore.Mvc.TagHelpers.ScriptTagHelper(IHostingEnvironment,IMemoryCache,HtmlEncoder,JavaScriptEncoder,IUrlHelperFactory)
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAdapter(RazorPageBase)
Properties
Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.CookieDomain
Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.CookieName
Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.CookiePath
Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.RequireSsl
Microsoft.AspNetCore.Mvc.ApiBehaviorOptions.AllowInferringBindingSourceForCollectionTypesAsFromQuery
Microsoft.AspNetCore.Mvc.ApiBehaviorOptions.SuppressUseValidationProblemDetailsForInvalidModelStateResponses
Microsoft.AspNetCore.Mvc.CookieTempDataProviderOptions.CookieName
Microsoft.AspNetCore.Mvc.CookieTempDataProviderOptions.Domain
Microsoft.AspNetCore.Mvc.CookieTempDataProviderOptions.Path
Microsoft.AspNetCore.Mvc.DataAnnotations.MvcDataAnnotationsLocalizationOptions.AllowDataAnnotationsLocalizationForEnumDisplayAttributes
Microsoft.AspNetCore.Mvc.Formatters.Xml.MvcXmlOptions.AllowRfc7807CompliantProblemDetailsFormat
Microsoft.AspNetCore.Mvc.MvcOptions.AllowBindingHeaderValuesToNonStringModelTypes
Microsoft.AspNetCore.Mvc.MvcOptions.AllowCombiningAuthorizeFilters
Microsoft.AspNetCore.Mvc.MvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent
Microsoft.AspNetCore.Mvc.MvcOptions.AllowValidatingTopLevelNodes
Microsoft.AspNetCore.Mvc.MvcOptions.InputFormatterExceptionPolicy
Microsoft.AspNetCore.Mvc.MvcOptions.SuppressBindingUndefinedValueToEnumType
Microsoft.AspNetCore.Mvc.MvcViewOptions.AllowRenderingMaxLengthAttribute
Microsoft.AspNetCore.Mvc.MvcViewOptions.SuppressTempDataAttributePrefix
Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions.AllowAreas
Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions.AllowDefaultHandlingForOptionsRequests
Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions.AllowMappingHeadRequestsToGetHandler
Methods
Microsoft.AspNetCore.Mvc.LocalRedirectResult.ExecuteResult(ActionContext)
Microsoft.AspNetCore.Mvc.RedirectResult.ExecuteResult(ActionContext)
Microsoft.AspNetCore.Mvc.RedirectToActionResult.ExecuteResult(ActionContext)
Microsoft.AspNetCore.Mvc.RedirectToPageResult.ExecuteResult(ActionContext)
Microsoft.AspNetCore.Mvc.RedirectToRouteResult.ExecuteResult(ActionContext)
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext,IValueProvider,ParameterDescriptor)
To better maintain the public API surface of ASP.NET Core, most of the types in *.Internal
namespaces (referred to as "pubternal" APIs) have become truly internal. Members in these namespaces were never meant to be supported as public-facing APIs. The APIs could break in minor releases and often did. Code that depends on these APIs breaks when updating to ASP.NET Core 3.0.
For more information, see dotnet/aspnetcore#4932 and dotnet/aspnetcore#11312.
3.0
The affected APIs are marked with the public
access modifier and exist in *.Internal
namespaces.
The affected APIs are marked with the internal access modifier and can no longer be used by code outside that assembly.
The guidance for these "pubternal" APIs was that they:
Leaving the APIs public
(even in the *.Internal
namespaces) was confusing to customers.
Stop using these "pubternal" APIs. If you have questions about alternate APIs, open an issue in the dotnet/aspnetcore repository.
For example, consider the following HTTP request buffering code in an ASP.NET Core 2.2 project. The EnableRewind
extension method exists in the Microsoft.AspNetCore.Http.Internal
namespace.
HttpContext.Request.EnableRewind();
In an ASP.NET Core 3.0 project, replace the EnableRewind
call with a call to the EnableBuffering
extension method. The request buffering feature works as it did in the past. EnableBuffering
calls the now internal
API.
HttpContext.Request.EnableBuffering();
ASP.NET Core
All APIs in the Microsoft.AspNetCore.*
and Microsoft.Extensions.*
namespaces that have an Internal
segment in the namespace name. For example:
Microsoft.AspNetCore.Authentication.Internal
Microsoft.AspNetCore.Builder.Internal
Microsoft.AspNetCore.DataProtection.Cng.Internal
Microsoft.AspNetCore.DataProtection.Internal
Microsoft.AspNetCore.Hosting.Internal
Microsoft.AspNetCore.Http.Internal
Microsoft.AspNetCore.Mvc.Core.Infrastructure
Microsoft.AspNetCore.Mvc.Core.Internal
Microsoft.AspNetCore.Mvc.Cors.Internal
Microsoft.AspNetCore.Mvc.DataAnnotations.Internal
Microsoft.AspNetCore.Mvc.Formatters.Internal
Microsoft.AspNetCore.Mvc.Formatters.Json.Internal
Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
Microsoft.AspNetCore.Mvc.Internal
Microsoft.AspNetCore.Mvc.ModelBinding.Internal
Microsoft.AspNetCore.Mvc.Razor.Internal
Microsoft.AspNetCore.Mvc.RazorPages.Internal
Microsoft.AspNetCore.Mvc.TagHelpers.Internal
Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
Microsoft.AspNetCore.Rewrite.Internal
Microsoft.AspNetCore.Routing.Internal
Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
Microsoft.AspNetCore.Server.Kestrel.Https.Internal
Google is starting to shut down Google+ Sign-in for apps as early as January 28, 2019.
ASP.NET 4.x and ASP.NET Core have been using the Google+ Sign-in APIs to authenticate Google account users in web apps. The affected NuGet packages are Microsoft.AspNetCore.Authentication.Google for ASP.NET Core and Microsoft.Owin.Security.Google for Microsoft.Owin
with ASP.NET Web Forms and MVC.
Google's replacement APIs use a different data source and format. The mitigations and solutions provided below account for the structural changes. Apps should verify the data itself still satisfies their requirements. For example, names, email addresses, profile links, and profile photos may provide subtly different values than before.
All versions. This change is external to ASP.NET Core.
For Microsoft.Owin
3.1.0 and later, a temporary mitigation is outlined here. Apps should complete testing with the mitigation to check for changes in the data format. There are plans to release Microsoft.Owin
4.0.1 with a fix. Apps using any prior version should update to version 4.0.1.
The mitigation in Owin with ASP.NET Web Forms and MVC can be adapted to ASP.NET Core 1.x. NuGet package patches aren't planned because 1.x has reached end of life status.
For Microsoft.AspNetCore.Authentication.Google
version 2.x, replace your existing call to AddGoogle
in Startup.ConfigureServices
with the following code:
.AddGoogle(o =>
{
o.ClientId = Configuration["Authentication:Google:ClientId"];
o.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
o.UserInformationEndpoint = "https://www.googleapis.com/oauth2/v2/userinfo";
o.ClaimActions.Clear();
o.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
o.ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
o.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "given_name");
o.ClaimActions.MapJsonKey(ClaimTypes.Surname, "family_name");
o.ClaimActions.MapJsonKey("urn:google:profile", "link");
o.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
});
The February 2.1 and 2.2 patches incorporated the preceding reconfiguration as the new default. No patch is planned for ASP.NET Core 2.0 since it has reached end of life.
The mitigation given for ASP.NET Core 2.x can also be used for ASP.NET Core 3.0. In future 3.0 previews, the Microsoft.AspNetCore.Authentication.Google
package may be removed. Users would be directed to Microsoft.AspNetCore.Authentication.OpenIdConnect
instead. The following code shows how to replace AddGoogle
with AddOpenIdConnect
in Startup.ConfigureServices
. This replacement can be used with ASP.NET Core 2.0 and later and can be adapted for ASP.NET Core 1.x as needed.
.AddOpenIdConnect("Google", o =>
{
o.ClientId = Configuration["Authentication:Google:ClientId"];
o.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
o.Authority = "https://accounts.google.com";
o.ResponseType = OpenIdConnectResponseType.Code;
o.CallbackPath = "/signin-google"; // Or register the default "/signin-oidc"
o.Scope.Add("email");
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
ASP.NET Core
Microsoft.AspNetCore.Authentication.Google
The deprecated Authentication
property on HttpContext
has been removed.
As part of dotnet/aspnetcore#6504, the deprecated Authentication
property on HttpContext
has been removed. The Authentication
property has been deprecated since 2.0. A migration guide was published to migrate code using this deprecated property to the new replacement APIs. The remaining unused classes / APIs related to the old ASP.NET Core 1.x authentication stack were removed in commit dotnet/aspnetcore@d7a7c65.
For discussion, see dotnet/aspnetcore#6533.
3.0
ASP.NET Core 1.0 APIs have been replaced by extension methods in Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.
See the migration guide.
ASP.NET Core
In ASP.NET Core 3.0, Newtonsoft.Json
types used in Authentication APIs have been replaced with System.Text.Json
types. Except for the following cases, basic usage of the Authentication packages remains unaffected:
For more information, see dotnet/aspnetcore#7105. For discussion, see dotnet/aspnetcore#7289.
3.0
For derived OAuth implementations, the most common change is to replace JObject.Parse
with JsonDocument.Parse
in the CreateTicketAsync
override as shown here. JsonDocument
implements IDisposable
.
The following list outlines known changes:
ClaimAction.Run(JsonElement userData, ClaimsIdentity identity, string issuer)
. All derived implementations of ClaimAction
are similarly affected.MapCustomJson(this ClaimActionCollection collection, string claimType, Func<JsonElement, string> resolver)
MapCustomJson(this ClaimActionCollection collection, string claimType, string valueType, Func<JsonElement, string> resolver)
JObject
with JsonElement
. The User
property and RunClaimActions
method have been updated to match.JsonDocument
instead of JObject
. The Response
property has been updated to match. OAuthTokenResponse
is now disposable and will be disposed by OAuthHandler
. Derived OAuth implementations overriding ExchangeCodeAsync
don't need to dispose the JsonDocument
or OAuthTokenResponse
.JObject
to JsonDocument
.JObject
to JsonElement
.JObject
to JsonElement
. The replacement method is TwitterHandler.CreateTicketAsync(ClaimsIdentity, AuthenticationProperties, AccessToken, JsonElement).ASP.NET Core
In ASP.NET Core 3.0, the signature of OAuthHandler.ExchangeCodeAsync
was changed from:
protected virtual System.Threading.Tasks.Task<Microsoft.AspNetCore.Authentication.OAuth.OAuthTokenResponse> ExchangeCodeAsync(string code, string redirectUri) { throw null; }
To:
protected virtual System.Threading.Tasks.Task<Microsoft.AspNetCore.Authentication.OAuth.OAuthTokenResponse> ExchangeCodeAsync(Microsoft.AspNetCore.Authentication.OAuth.OAuthCodeExchangeContext context) { throw null; }
3.0
The code
and redirectUri
strings were passed as separate arguments.
Code
and RedirectUri
are properties on OAuthCodeExchangeContext
that can be set via the OAuthCodeExchangeContext
constructor. The new OAuthCodeExchangeContext
type is the only argument passed to OAuthHandler.ExchangeCodeAsync
.
This change allows additional parameters to be provided in a non-breaking manner. There's no need to create new ExchangeCodeAsync
overloads.
Construct an OAuthCodeExchangeContext
with the appropriate code
and redirectUri
values. An AuthenticationProperties instance must be provided. This single OAuthCodeExchangeContext
instance can be passed to OAuthHandler.ExchangeCodeAsync
instead of multiple arguments.
ASP.NET Core
OAuthHandler<TOptions>.ExchangeCodeAsync(String, String)
The core AddAuthorization
methods that used to reside in Microsoft.AspNetCore.Authorization
were renamed to AddAuthorizationCore
. The old AddAuthorization
methods still exist, but are in the Microsoft.AspNetCore.Authorization.Policy
assembly instead. Apps using both methods should see no impact. Note that Microsoft.AspNetCore.Authorization.Policy
now ships in the shared framework rather than a standalone package as discussed in Shared framework: Assemblies removed from Microsoft.AspNetCore.App.
3.0
AddAuthorization
methods existed in Microsoft.AspNetCore.Authorization
.
AddAuthorization
methods exist in Microsoft.AspNetCore.Authorization.Policy
. AddAuthorizationCore
is the new name for the old methods.
AddAuthorization
is a better method name for adding all common services needed for authorization.
Either add a reference to Microsoft.AspNetCore.Authorization.Policy
or use AddAuthorizationCore
instead.
ASP.NET Core
As of ASP.NET Core 3.0, MVC doesn't add AllowAnonymousFilters for [AllowAnonymous] attributes that were discovered on controllers and action methods. This change is addressed locally for derivatives of AuthorizeAttribute, but it's a breaking change for IAsyncAuthorizationFilter and IAuthorizationFilter implementations. Such implementations wrapped in a [TypeFilter] attribute are a popular and supported way to achieve strongly-typed, attribute-based authorization when both configuration and dependency injection are required.
3.0
IAllowAnonymous appeared in the AuthorizationFilterContext.Filters collection. Testing for the interface's presence was a valid approach to override or disable the filter on individual controller methods.
IAllowAnonymous
no longer appears in the AuthorizationFilterContext.Filters
collection. IAsyncAuthorizationFilter
implementations that are dependent on the old behavior typically cause intermittent HTTP 401 Unauthorized or HTTP 403 Forbidden responses.
A new endpoint routing strategy was introduced in ASP.NET Core 3.0.
Search the endpoint metadata for IAllowAnonymous
. For example:
var endpoint = context.HttpContext.GetEndpoint();
if (endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null)
{
}
An example of this technique is seen in this HasAllowAnonymous method.
ASP.NET Core
None
In ASP.NET Core 3.0, a new GetFallbackPolicyAsync
method was added to IAuthorizationPolicyProvider
. This fallback policy is used by the authorization middleware when no policy is specified.
For more information, see dotnet/aspnetcore#9759.
3.0
Implementations of IAuthorizationPolicyProvider
didn't require a GetFallbackPolicyAsync
method.
Implementations of IAuthorizationPolicyProvider
require a GetFallbackPolicyAsync
method.
A new method was needed for the new AuthorizationMiddleware
to use when no policy is specified.
Add the GetFallbackPolicyAsync
method to your implementations of IAuthorizationPolicyProvider
.
ASP.NET Core
Microsoft.AspNetCore.Authorization.IAuthorizationPolicyProvider
The ASP.NET Core 3.0 release removed the obsolete MemoryCacheOptions APIs.
This change is a follow-up to aspnet/Caching#221. For discussion, see dotnet/extensions#1062.
3.0
MemoryCacheOptions.CompactOnMemoryPressure
property was available.
The MemoryCacheOptions.CompactOnMemoryPressure
property has been removed.
Automatically compacting the cache caused problems. To avoid unexpected behavior, the cache should only be compacted when needed.
To compact the cache, downcast to MemoryCache
and call Compact
when needed.
ASP.NET Core
MemoryCacheOptions.CompactOnMemoryPressure
The Microsoft.Extensions.Caching.SqlServer
package will use the new Microsoft.Data.SqlClient
package instead of System.Data.SqlClient
package. This change could cause slight behavioral breaking changes. For more information, see Introducing the new Microsoft.Data.SqlClient.
3.0
The Microsoft.Extensions.Caching.SqlServer
package used the System.Data.SqlClient
package.
Microsoft.Extensions.Caching.SqlServer
is now using the Microsoft.Data.SqlClient
package.
Microsoft.Data.SqlClient
is a new package that is built off of System.Data.SqlClient
. It's where all new feature work will be done from now on.
Customers shouldn't need to worry about this breaking change unless they were using types returned by the Microsoft.Extensions.Caching.SqlServer
package and casting them to System.Data.SqlClient
types. For example, if someone was casting a DbConnection
to the old SqlConnection type, they would need to change the cast to the new Microsoft.Data.SqlClient.SqlConnection
type.
ASP.NET Core
None
In ASP.NET Core 3.0, "pubternal" types in ResponseCaching
have been changed to internal
.
In addition, default implementations of IResponseCachingPolicyProvider
and IResponseCachingKeyProvider
are no longer added to services as part of the AddResponseCaching
method.
In ASP.NET Core, "pubternal" types are declared as public
but reside in a namespace suffixed with .Internal
. While these types are public, they have no support policy and are subject to breaking changes. Unfortunately, accidental use of these types has been common, resulting in breaking changes to these projects and limiting the ability to maintain the framework.
3.0
These types were publicly visible, but unsupported.
These types are now internal
.
The internal
scope better reflects the unsupported policy.
Copy types that are used by your app or library.
ASP.NET Core
Microsoft.AspNetCore.ResponseCaching.Internal.CachedResponse
Microsoft.AspNetCore.ResponseCaching.Internal.CachedVaryByRules
Microsoft.AspNetCore.ResponseCaching.Internal.IResponseCache
Microsoft.AspNetCore.ResponseCaching.Internal.IResponseCacheEntry
Microsoft.AspNetCore.ResponseCaching.Internal.IResponseCachingKeyProvider
Microsoft.AspNetCore.ResponseCaching.Internal.IResponseCachingPolicyProvider
Microsoft.AspNetCore.ResponseCaching.Internal.MemoryResponseCache
Microsoft.AspNetCore.ResponseCaching.Internal.ResponseCachingContext
Microsoft.AspNetCore.ResponseCaching.Internal.ResponseCachingKeyProvider
Microsoft.AspNetCore.ResponseCaching.Internal.ResponseCachingPolicyProvider
Azure.Extensions.AspNetCore.DataProtection.Blobs
depends on the Azure Storage libraries. These libraries renamed their assemblies, packages, and namespaces. Starting in ASP.NET Core 3.0, Azure.Extensions.AspNetCore.DataProtection.Blobs
uses the new Azure.Storage.
-prefixed APIs and packages.
For questions about the Azure Storage APIs, use https://github.com/Azure/azure-storage-net. For discussion on this issue, see dotnet/aspnetcore#19570.
3.0
The package referenced the WindowsAzure.Storage
NuGet package.
The package references the Microsoft.Azure.Storage.Blob
NuGet package.
The package references the Azure.Storage.Blob
NuGet package.
This change allows Azure.Extensions.AspNetCore.DataProtection.Blobs
to migrate to the recommended Azure Storage packages.
If you still need to use the older Azure Storage APIs with ASP.NET Core 3.0, add a direct dependency to the package WindowsAzure.Storage or Microsoft.Azure.Storage. This package can be installed alongside the new Azure.Storage
APIs.
In many cases, the upgrade only involves changing the using
statements to use the new namespaces:
- using Microsoft.WindowsAzure.Storage;
- using Microsoft.WindowsAzure.Storage.Blob;
- using Microsoft.Azure.Storage;
- using Microsoft.Azure.Storage.Blob;
+ using Azure.Storage;
+ using Azure.Storage.Blobs;
ASP.NET Core
None
Starting with ASP.NET Core 3.0, the Windows Hosting Bundle won't contain AspNetCoreModule (ANCM) V1.
ANCM V2 is backwards compatible with ANCM OutOfProcess and is recommended for use with ASP.NET Core 3.0 apps.
For discussion, see dotnet/aspnetcore#7095.
3.0
ANCM V1 is included in the Windows Hosting Bundle.
ANCM V1 isn't included in the Windows Hosting Bundle.
ANCM V2 is backwards compatible with ANCM OutOfProcess and is recommended for use with ASP.NET Core 3.0 apps.
Use ANCM V2 with ASP.NET Core 3.0 apps.
If ANCM V1 is required, it can be installed using the ASP.NET Core 2.1 or 2.2 Windows Hosting Bundle.
This change will break ASP.NET Core 3.0 apps that:
<AspNetCoreModuleName>AspNetCoreModule</AspNetCoreModuleName>
.<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
.ASP.NET Core
None
The only types the generic host supports for Startup
class constructor injection are IHostEnvironment
, IWebHostEnvironment
, and IConfiguration
. Apps using WebHost
are unaffected.
Prior to ASP.NET Core 3.0, constructor injection could be used for arbitrary types in the Startup
class's constructor. In ASP.NET Core 3.0, the web stack was replatformed onto the generic host library. You can see the change in the Program.cs file of the templates:
ASP.NET Core 2.x:
ASP.NET Core 3.0:
Host
uses one dependency injection (DI) container to build the app. WebHost
uses two containers: one for the host and one for the app. As a result, the Startup
constructor no longer supports custom service injection. Only IHostEnvironment
, IWebHostEnvironment
, and IConfiguration
can be injected. This change prevents DI issues such as the duplicate creation of a singleton service.
3.0
This change is a consequence of replatforming the web stack onto the generic host library.
Inject services into the Startup.Configure
method signature. For example:
public void Configure(IApplicationBuilder app, IOptions<MyOptions> options)
ASP.NET Core
None
Version 13.0.19218.0 of the ASP.NET Core Module (ANCM) for hosting via IIS out-of-process enables an existing HTTPS redirection feature for ASP.NET Core 3.0 and 2.2 apps.
For discussion, see dotnet/AspNetCore#15243.
3.0
The ASP.NET Core 2.1 project template first introduced support for HTTPS middleware methods like UseHttpsRedirection and UseHsts. Enabling HTTPS redirection required the addition of configuration, since apps in development don't use the default port of 443. HTTP Strict Transport Security (HSTS) is active only if the request is already using HTTPS. Localhost is skipped by default.
In ASP.NET Core 3.0, the IIS HTTPS scenario was enhanced. With the enhancement, an app could discover the server's HTTPS ports and make UseHttpsRedirection
work by default. The in-process component accomplished port discovery with the IServerAddresses
feature, which only affects ASP.NET Core 3.0 apps because the in-process library is versioned with the framework. The out-of-process component changed to automatically add the ASPNETCORE_HTTPS_PORT
environment variable. This change affected both ASP.NET Core 2.2 and 3.0 apps because the out-of-process component is shared globally. ASP.NET Core 2.1 apps aren't affected because they use a prior version of ANCM by default.
The preceding behavior was modified in ASP.NET Core 3.0.1 and 3.1.0 Preview 3 to reverse the behavior changes in ASP.NET Core 2.x. These changes only affect IIS out-of-process apps.
As detailed above, installing ASP.NET Core 3.0.0 had the side effect of also activating the UseHttpsRedirection
middleware in ASP.NET Core 2.x apps. A change was made to ANCM in ASP.NET Core 3.0.1 and 3.1.0 Preview 3 such that installing them no longer has this effect on ASP.NET Core 2.x apps. The ASPNETCORE_HTTPS_PORT
environment variable that ANCM populated in ASP.NET Core 3.0.0 was changed to ASPNETCORE_ANCM_HTTPS_PORT
in ASP.NET Core 3.0.1 and 3.1.0 Preview 3. UseHttpsRedirection
was also updated in these releases to understand both the new and old variables. ASP.NET Core 2.x won't be updated. As a result, it reverts to the previous behavior of being disabled by default.
Improved ASP.NET Core 3.0 functionality.
No action is required if you want all clients to use HTTPS. To allow some clients to use HTTP, take one of the following steps:
Remove the calls to UseHttpsRedirection
and UseHsts
from your project's Startup.Configure
method, and redeploy the app.
In your web.config file, set the ASPNETCORE_HTTPS_PORT
environment variable to an empty string. This change can occur directly on the server without redeploying the app. For example:
<aspNetCore processPath="dotnet" arguments=".\WebApplication3.dll" stdoutLogEnabled="false" stdoutLogFile="\\?\%home%\LogFiles\stdout" >
<environmentVariables>
<environmentVariable name="ASPNETCORE_HTTPS_PORT" value="" />
</environmentVariables>
</aspNetCore>
UseHttpsRedirection
can still be:
ASPNETCORE_HTTPS_PORT
environment variable to the appropriate port number (443 in most production scenarios).ASPNETCORE_ANCM_HTTPS_PORT
with an empty string value. This value is set in the same fashion as the preceding ASPNETCORE_HTTPS_PORT
example.Machines running ASP.NET Core 3.0.0 apps should install the ASP.NET Core 3.0.1 runtime before installing the ASP.NET Core 3.1.0 Preview 3 ANCM. Doing so ensures that UseHttpsRedirection
continues to operate as expected for the ASP.NET Core 3.0 apps.
In Azure App Service, ANCM deploys on a separate schedule from the runtime because of its global nature. ANCM was deployed to Azure with these changes after ASP.NET Core 3.0.1 and 3.1.0 were deployed.
ASP.NET Core
HttpsPolicyBuilderExtensions.UseHttpsRedirection(IApplicationBuilder)
New types have been introduced to replace existing IHostingEnvironment
and IApplicationLifetime
types.
3.0
There were two different IHostingEnvironment
and IApplicationLifetime
types from Microsoft.Extensions.Hosting
and Microsoft.AspNetCore.Hosting
.
The old types have been marked as obsolete and replaced with new types.
When Microsoft.Extensions.Hosting
was introduced in ASP.NET Core 2.1, some types like IHostingEnvironment
and IApplicationLifetime
were copied from Microsoft.AspNetCore.Hosting
. Some ASP.NET Core 3.0 changes cause apps to include both the Microsoft.Extensions.Hosting
and Microsoft.AspNetCore.Hosting
namespaces. Any use of those duplicate types causes an "ambiguous reference" compiler error when both namespaces are referenced.
Replaced any usages of the old types with the newly introduced types as below:
Obsolete types (warning):
New types:
Microsoft.AspNetCore.Hosting.IWebHostEnvironment : IHostEnvironment
The new IHostEnvironment
IsDevelopment
and IsProduction
extension methods are in the Microsoft.Extensions.Hosting
namespace. That namespace may need to be added to your project.
ASP.NET Core
As part of making ASP.NET Core more pay for play, the ObjectPoolProvider
was removed from the main set of dependencies. Specific components relying on ObjectPoolProvider
now add it themselves.
For discussion, see dotnet/aspnetcore#5944.
3.0
WebHostBuilder
provides ObjectPoolProvider
by default in the DI container.
WebHostBuilder
no longer provides ObjectPoolProvider
by default in the DI container.
This change was made to make ASP.NET Core more pay for play.
If your component requires ObjectPoolProvider
, it needs to be added to your dependencies via the IServiceCollection
.
ASP.NET Core
None
As part of ASP.NET Core 3.0 performance improvements, the extensibility of DefaultHttpContext
was removed. The class is now sealed
. For more information, see dotnet/aspnetcore#6504.
If your unit tests use Mock<DefaultHttpContext>
, use Mock<HttpContext>
or new DefaultHttpContext()
instead.
For discussion, see dotnet/aspnetcore#6534.
3.0
Classes can derive from DefaultHttpContext
.
Classes can't derive from DefaultHttpContext
.
The extensibility was provided initially to allow pooling of the HttpContext
, but it introduced unnecessary complexity and impeded other optimizations.
If you're using Mock<DefaultHttpContext>
in your unit tests, begin using Mock<HttpContext>
instead.
ASP.NET Core
Microsoft.AspNetCore.Http.DefaultHttpContext
Starting in ASP.NET Core 3.0 Preview 5, the fields in Microsoft.Net.Http.Headers.HeaderNames changed from const
to static readonly
.
For discussion, see dotnet/aspnetcore#9514.
3.0
These fields used to be const
.
These fields are now static readonly
.
The change:
Recompile against 3.0. Source code using these fields in the following ways can no longer do so:
case
in a switch
statementconst
To work around the breaking change, switch to using self-defined header name constants or string literals.
ASP.NET Core
Microsoft.Net.Http.Headers.HeaderNames
The infrastructure backing an HTTP response body has changed. If you're using HttpResponse
directly, you shouldn't need to make any code changes. Read further if you're wrapping or replacing HttpResponse.Body
or accessing HttpContext.Features
.
3.0
There were three APIs associated with the HTTP response body:
IHttpResponseFeature.Body
IHttpSendFileFeature.SendFileAsync
IHttpBufferingFeature.DisableResponseBuffering
If you replace HttpResponse.Body
, it replaces the entire IHttpResponseBodyFeature
with a wrapper around your given stream using StreamResponseBodyFeature
to provide default implementations for all of the expected APIs. Setting back the original stream reverts this change.
The motivation is to combine the response body APIs into a single new feature interface.
Use IHttpResponseBodyFeature
where you previously were using IHttpResponseFeature.Body
,
IHttpSendFileFeature
, or IHttpBufferingFeature
.
ASP.NET Core
SameSite
is an option for cookies that can help mitigate some Cross-Site Request Forgery (CSRF) attacks. When this option was initially introduced, inconsistent defaults were used across various ASP.NET Core APIs. The inconsistency has led to confusing results. As of ASP.NET Core 3.0, these defaults are better aligned. You must opt in to this feature on a per-component basis.
3.0
Similar ASP.NET Core APIs used different default SameSiteMode values. An example of the inconsistency is seen in HttpResponse.Cookies.Append(String, String)
and HttpResponse.Cookies.Append(String, String, CookieOptions)
, which defaulted to SameSiteMode.None
and SameSiteMode.Lax
, respectively.
All the affected APIs default to SameSiteMode.None
.
The default value was changed to make SameSite
an opt-in feature.
Each component that emits cookies needs to decide if SameSite
is appropriate for its scenarios. Review your usage of the affected APIs and reconfigure SameSite
as needed.
ASP.NET Core
Starting with ASP.NET Core 3.0, synchronous server operations are disabled by default.
AllowSynchronousIO
is an option in each server that enables or disables synchronous IO APIs like HttpRequest.Body.Read
, HttpResponse.Body.Write
, and Stream.Flush
. These APIs have long been a source of thread starvation and app hangs. Starting in ASP.NET Core 3.0 Preview 3, these synchronous operations are disabled by default.
Affected servers:
Expect errors similar to:
Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.
Synchronous operations are disallowed. Call FlushAsync or set AllowSynchronousIO to true instead.
Each server has an AllowSynchronousIO
option that controls this behavior and the default for all of them is now false
.
The behavior can also be overridden on a per-request basis as a temporary mitigation. For example:
var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();
if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
}
If you have trouble with a TextWriter
or another stream calling a synchronous API in Dispose
, call the new DisposeAsync
API instead.
For discussion, see dotnet/aspnetcore#7644.
3.0
HttpRequest.Body.Read
, HttpResponse.Body.Write
, and Stream.Flush
were allowed by default.
These synchronous APIs are disallowed by default:
Expect errors similar to:
Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.
Synchronous operations are disallowed. Call FlushAsync or set AllowSynchronousIO to true instead.
These synchronous APIs have long been a source of thread starvation and app hangs. Starting in ASP.NET Core 3.0 Preview 3, the synchronous operations are disabled by default.
Use the asynchronous versions of the methods. The behavior can also be overridden on a per-request basis as a temporary mitigation.
var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();
if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
}
ASP.NET Core
Starting with ASP.NET Core 3.0, the IdentityBuilderUIExtensions.AddDefaultUI(IdentityBuilder,UIFramework) method overload no longer exists.
3.0
This change was a result of adoption of the static web assets feature.
Call IdentityBuilderUIExtensions.AddDefaultUI(IdentityBuilder) instead of the overload that takes two arguments. If you're using Bootstrap 3, also add the following line to a <PropertyGroup>
element in your project file:
<IdentityUIFrameworkVersion>Bootstrap3</IdentityUIFrameworkVersion>
ASP.NET Core
IdentityBuilderUIExtensions.AddDefaultUI(IdentityBuilder,UIFramework)
Starting in ASP.NET Core 3.0, Identity UI defaults to using version 4 of Bootstrap.
3.0
The services.AddDefaultIdentity<IdentityUser>().AddDefaultUI();
method call was the same as services.AddDefaultIdentity<IdentityUser>().AddDefaultUI(UIFramework.Bootstrap3);
The services.AddDefaultIdentity<IdentityUser>().AddDefaultUI();
method call is the same as services.AddDefaultIdentity<IdentityUser>().AddDefaultUI(UIFramework.Bootstrap4);
Bootstrap 4 was released during ASP.NET Core 3.0 timeframe.
You're impacted by this change if you use the default Identity UI and have added it in Startup.ConfigureServices
as shown in the following example:
services.AddDefaultIdentity<IdentityUser>().AddDefaultUI();
Take one of the following actions:
Migrate your app to use Bootstrap 4 using their migration guide.
Update Startup.ConfigureServices
to enforce usage of Bootstrap 3. For example:
services.AddDefaultIdentity<IdentityUser>().AddDefaultUI(UIFramework.Bootstrap3);
ASP.NET Core
None
By default, SignInAsync
throws an exception for principals / identities in which IsAuthenticated
is false
.
3.0
SignInAsync
accepts any principals / identities, including identities in which IsAuthenticated
is false
.
By default, SignInAsync
throws an exception for principals / identities in which IsAuthenticated
is false
. There's a new flag to suppress this behavior, but the default behavior has changed.
The old behavior was problematic because, by default, these principals were rejected by [Authorize]
/ RequireAuthenticatedUser()
.
In ASP.NET Core 3.0 Preview 6, there's a RequireAuthenticatedSignIn
flag on AuthenticationOptions
that is true
by default. Set this flag to false
to restore the old behavior.
ASP.NET Core
None
Starting with ASP.NET Core 3.0, a new IUserConfirmation<TUser>
parameter was added to the SignInManager
constructor. For more information, see dotnet/aspnetcore#8356.
3.0
The motivation for the change was to add support for new email / confirmation flows in Identity.
If manually constructing a SignInManager
, provide an implementation of IUserConfirmation
or grab one from dependency injection to provide.
ASP.NET Core
ASP.NET Core 3.0 introduced a static web assets feature, and Identity UI has adopted it.
As a result of Identity UI adopting the static web assets feature:
IdentityUIFrameworkVersion
property in your project file.3.0
The default UI framework for Identity UI was Bootstrap 3. The UI framework could be configured using a parameter to the AddDefaultUI
method call in Startup.ConfigureServices
.
The default UI framework for Identity UI is Bootstrap 4. The UI framework must be configured in your project file, instead of in the AddDefaultUI
method call.
Adoption of the static web assets feature required that the UI framework configuration move to MSBuild. The decision on which framework to embed is a build-time decision, not a runtime decision.
Review your site UI to ensure the new Bootstrap 4 components are compatible. If necessary, use the IdentityUIFrameworkVersion
MSBuild property to revert to Bootstrap 3. Add the property to a <PropertyGroup>
element in your project file:
<IdentityUIFrameworkVersion>Bootstrap3</IdentityUIFrameworkVersion>
ASP.NET Core
IdentityBuilderUIExtensions.AddDefaultUI(IdentityBuilder, UIFramework)
As part of the move to move "pubternal" APIs to public
, the concept of an IConnectionAdapter
was removed from Kestrel. Connection adapters are being replaced with connection middleware (similar to HTTP middleware in the ASP.NET Core pipeline, but for lower-level connections). HTTPS and connection logging have moved from connection adapters to connection middleware. Those extension methods should continue to work seamlessly, but the implementation details have changed.
For more information, see dotnet/aspnetcore#11412. For discussion, see dotnet/aspnetcore#11475.
3.0
Kestrel extensibility components were created using IConnectionAdapter
.
Kestrel extensibility components are created as middleware.
This change is intended to provide a more flexible extensibility architecture.
Convert any implementations of IConnectionAdapter
to use the new middleware pattern as shown here.
ASP.NET Core
Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal.IConnectionAdapter
The assembly Microsoft.AspNetCore.Server.Kestrel.Https has been removed.
3.0
In ASP.NET Core 2.1, the contents of Microsoft.AspNetCore.Server.Kestrel.Https
were moved to Microsoft.AspNetCore.Server.Kestrel.Core. This change was done in a non-breaking way using [TypeForwardedTo]
attributes.
Microsoft.AspNetCore.Server.Kestrel.Https
2.0 should update all ASP.NET Core dependencies to 2.1 or later. Otherwise, they may break when loaded into an ASP.NET Core 3.0 app.Microsoft.AspNetCore.Server.Kestrel.Https
NuGet package.ASP.NET Core
None
In prior versions, Kestrel added HTTP/1.1 chunked trailer headers into the request headers collection when the request body was read to the end. This behavior caused concerns about ambiguity between headers and trailers. The decision was made to move the trailers to a new collection.
HTTP/2 request trailers were unavailable in ASP.NET Core 2.2 but are now also available in this new collection in ASP.NET Core 3.0.
New request extension methods have been added to access these trailers.
HTTP/1.1 trailers are available once the entire request body has been read.
HTTP/2 trailers are available once they're received from the client. The client won't send the trailers until the entire request body has been at least buffered by the server. You may need to read the request body to free up buffer space. Trailers are always available if you read the request body to the end. The trailers mark the end of the body.
3.0
Request trailer headers would be added to the HttpRequest.Headers
collection.
Request trailer headers aren't present in the HttpRequest.Headers
collection. Use the following extension methods on HttpRequest
to access them:
GetDeclaredTrailers()
- Gets the request "Trailer" header that lists which trailers to expect after the body.SupportsTrailers()
- Indicates if the request supports receiving trailer headers.CheckTrailersAvailable()
- Determines if the request supports trailers and if they're available for reading.GetTrailer(string trailerName)
- Gets the requested trailing header from the response.Trailers are a key feature in scenarios like gRPC. Merging the trailers in to request headers was confusing to users.
Use the trailer-related extension methods on HttpRequest
to access trailers.
ASP.NET Core
As part of moving away from "pubternal" APIs, the Kestrel transport layer APIs are exposed as a public interface in the Microsoft.AspNetCore.Connections.Abstractions
library.
3.0
Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
library.ListenOptions.NoDelay
property was available.IConnectionListener
interface was introduced in the Microsoft.AspNetCore.Connections.Abstractions
library to expose the most used functionality from the ...Transport.Abstractions
library.NoDelay
is now available in transport options (LibuvTransportOptions
and SocketTransportOptions
).SchedulingMode
is no longer available.ASP.NET Core 3.0 has moved away from "pubternal" APIs.
ASP.NET Core
None
The ResourceManagerWithCultureStringLocalizer class and WithCulture interface member are often sources of confusion for users of localization, especially when creating their own IStringLocalizer
implementation. These items give the user the impression that an IStringLocalizer
instance is "per-language, per-resource". In reality, the instances should only be "per-resource". The language searched for is determined by the CultureInfo.CurrentUICulture
at execution time. To eliminate the source of confusion, the APIs were marked as obsolete in ASP.NET Core 3.0. The APIs will be removed in a future release.
For context, see dotnet/aspnetcore#3324. For discussion, see dotnet/aspnetcore#7756.
3.0
Methods weren't marked as Obsolete
.
Methods are marked Obsolete
.
The APIs represented a use case that isn't recommended. There was confusion about the design of localization.
The recommendation is to use ResourceManagerStringLocalizer
instead. Let the culture be set by the CurrentCulture
. If that isn't an option, create and use a copy of ResourceManagerWithCultureStringLocalizer.
ASP.NET Core
Microsoft.Extensions.Localization.ResourceManagerWithCultureStringLocalizer
Microsoft.Extensions.Localization.ResourceManagerStringLocalizer.WithCulture
Prior to ASP.NET Core 3.0, DebugLogger
's access modifier was public
. In ASP.NET Core 3.0, the access modifier changed to internal
.
3.0
The change is being made to:
ConsoleLogger
.Use the AddDebug ILoggingBuilder
extension method to enable debug logging. DebugLoggerProvider is also still public
in the event the service needs to be registered manually.
ASP.NET Core
Microsoft.Extensions.Logging.Debug.DebugLogger
As part of addressing dotnet/aspnetcore#4849, ASP.NET Core MVC trims the suffix Async
from action names by default. Starting with ASP.NET Core 3.0, this change affects both routing and link generation.
3.0
Consider the following ASP.NET Core MVC controller:
public class ProductController : Controller
{
public async IActionResult ListAsync()
{
var model = await DbContext.Products.ToListAsync();
return View(model);
}
}
The action is routable via Product/ListAsync
. Link generation requires specifying the Async
suffix. For example:
<a asp-controller="Product" asp-action="ListAsync">List</a>
In ASP.NET Core 3.0, the action is routable via Product/List
. Link generation code should omit the Async
suffix. For example:
<a asp-controller="Product" asp-action="List">List</a>
This change doesn't affect names specified using the [ActionName]
attribute. The new behavior can be disabled by setting MvcOptions.SuppressAsyncSuffixInActionNames
to false
in Startup.ConfigureServices
:
services.AddMvc(options =>
{
options.SuppressAsyncSuffixInActionNames = false;
});
By convention, asynchronous .NET methods are suffixed with Async
. However, when a method defines an MVC action, it's undesirable to use the Async
suffix.
If your app depends on MVC actions preserving the name's Async
suffix, choose one of the following mitigations:
[ActionName]
attribute to preserve the original name.MvcOptions.SuppressAsyncSuffixInActionNames
to false
in Startup.ConfigureServices
:services.AddMvc(options =>
{
options.SuppressAsyncSuffixInActionNames = false;
});
ASP.NET Core
None
JsonResult
has moved to the Microsoft.AspNetCore.Mvc.Core
assembly. This type used to be defined in Microsoft.AspNetCore.Mvc.Formatters.Json. An assembly-level [TypeForwardedTo] attribute was added to Microsoft.AspNetCore.Mvc.Formatters.Json
to address this issue for the majority of users. Apps that use third-party libraries may encounter issues.
3.0 Preview 6
An app using a 2.2-based library builds successfully.
An app using a 2.2-based library fails compilation. An error containing a variation of the following text is provided:
The type 'JsonResult' exists in both 'Microsoft.AspNetCore.Mvc.Core, Version=3.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' and 'Microsoft.AspNetCore.Mvc.Formatters.Json, Version=2.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'
For an example of such an issue, see dotnet/aspnetcore#7220.
Platform-level changes to the composition of ASP.NET Core as described at aspnet/Announcements#325.
Libraries compiled against the 2.2 version of Microsoft.AspNetCore.Mvc.Formatters.Json
may need to recompile to address the problem for all consumers. If affected, contact the library author. Request recompilation of the library to target ASP.NET Core 3.0.
ASP.NET Core
Microsoft.AspNetCore.Mvc.JsonResult
In ASP.NET Core 1.1, the Microsoft.AspNetCore.Mvc.Razor.ViewCompilation
(MVC precompilation tool) package was introduced to add support for publish-time compilation of Razor files (.cshtml files). In ASP.NET Core 2.1, the Razor SDK was introduced to expand upon features of the precompilation tool. The Razor SDK added support for build- and publish-time compilation of Razor files. The SDK verifies the correctness of .cshtml files at build time while improving on app startup time. The Razor SDK is on by default, and no gesture is required to start using it.
In ASP.NET Core 3.0, the ASP.NET Core 1.1-era MVC precompilation tool was removed. Earlier package versions will continue receiving important bug and security fixes in the patch release.
3.0
The Microsoft.AspNetCore.Mvc.Razor.ViewCompilation
package was used to pre-compile MVC Razor views.
The Razor SDK natively supports this functionality. The Microsoft.AspNetCore.Mvc.Razor.ViewCompilation
package is no longer updated.
The Razor SDK provides more functionality and verifies the correctness of .cshtml files at build time. The SDK also improves app startup time.
For users of ASP.NET Core 2.1 or later, update to use the native support for precompilation in the Razor SDK. If bugs or missing features prevent migration to the Razor SDK, open an issue at dotnet/aspnetcore.
ASP.NET Core
None
In ASP.NET Core 3.0, all "pubternal" types in MVC were updated to either be public
in a supported namespace or internal
as appropriate.
In ASP.NET Core, "pubternal" types are declared as public
but reside in a .Internal
-suffixed namespace. While these types are public
, they have no support policy and are subject to breaking changes. Unfortunately, accidental use of these types has been common, resulting in breaking changes to these projects and limiting the ability to maintain the framework.
3.0
Some types in MVC were public
but in a .Internal
namespace. These types had no support policy and were subject to breaking changes.
All such types are updated either to be public
in a supported namespace or marked as internal
.
Accidental use of the "pubternal" types has been common, resulting in breaking changes to these projects and limiting the ability to maintain the framework.
If you're using types that have become truly public
and have been moved into a new, supported namespace, update your references to match the new namespaces.
If you're using types that have become marked as internal
, you'll need to find an alternative. The previously "pubternal" types were never supported for public use. If there are specific types in these namespaces that are critical to your apps, file an issue at dotnet/aspnetcore. Considerations may be made for making the requested types public
.
ASP.NET Core
This change includes types in the following namespaces:
Microsoft.AspNetCore.Mvc.Cors.Internal
Microsoft.AspNetCore.Mvc.DataAnnotations.Internal
Microsoft.AspNetCore.Mvc.Formatters.Internal
Microsoft.AspNetCore.Mvc.Formatters.Json.Internal
Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
Microsoft.AspNetCore.Mvc.Internal
Microsoft.AspNetCore.Mvc.ModelBinding.Internal
Microsoft.AspNetCore.Mvc.Razor.Internal
Microsoft.AspNetCore.Mvc.RazorPages.Internal
Microsoft.AspNetCore.Mvc.TagHelpers.Internal
Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
Starting with ASP.NET Core 3.0, the Microsoft.AspNetCore.Mvc.WebApiCompatShim
package is no longer available.
The Microsoft.AspNetCore.Mvc.WebApiCompatShim
(WebApiCompatShim) package provides partial compatibility in ASP.NET Core with ASP.NET 4.x Web API 2 to simplify migrating existing Web API implementations to ASP.NET Core. However, apps using the WebApiCompatShim don't benefit from the API-related features shipping in recent ASP.NET Core releases. Such features include improved Open API specification generation, standardized error handling, and client code generation. To better focus the API efforts in 3.0, WebApiCompatShim was removed. Existing apps using the WebApiCompatShim should migrate to the newer [ApiController]
model.
3.0
The Web API compatibility shim was a migration tool. It restricts user access to new functionality added in ASP.NET Core.
Remove usage of this shim and migrate directly to the similar functionality in ASP.NET Core itself.
ASP.NET Core
Microsoft.AspNetCore.Mvc.WebApiCompatShim
The RazorTemplateEngine
API was removed and replaced with Microsoft.AspNetCore.Razor.Language.RazorProjectEngine
.
For discussion, see GitHub issue dotnet/aspnetcore#25215.
3.0
A template engine can be created and used to parse and generate code for Razor files.
RazorProjectEngine
can be created and provided the same type of information as RazorTemplateEngine
to parse and generate code for Razor files. RazorProjectEngine
also provides extra levels of configuration.
RazorTemplateEngine
was too tightly coupled to the existing implementations. This tight coupling led to more questions when trying to properly configure a Razor parsing/generation pipeline.
Use RazorProjectEngine
instead of RazorTemplateEngine
. Consider the following examples.
RazorProjectEngine projectEngine =
RazorProjectEngine.Create(RazorConfiguration.Default,
RazorProjectFileSystem.Create(@"C:\source\repos\ConsoleApp4\ConsoleApp4"),
builder =>
{
builder.ConfigureClass((document, classNode) =>
{
classNode.ClassName = "MyClassName";
// Can also configure other aspects of the class here.
});
// More configuration can go here
});
RazorProjectItem item = projectEngine.FileSystem.GetItem(
@"C:\source\repos\ConsoleApp4\ConsoleApp4\Example.cshtml",
FileKinds.Legacy);
RazorCodeDocument output = projectEngine.Process(item);
// Things available
RazorSyntaxTree syntaxTree = output.GetSyntaxTree();
DocumentIntermediateNode intermediateDocument =
output.GetDocumentIntermediateNode();
RazorCSharpDocument csharpDocument = output.GetCSharpDocument();
ASP.NET Core
RazorTemplateEngine
RazorTemplateEngineOptions
Support for runtime compilation of Razor views and Razor Pages has moved to a separate package.
3.0
Runtime compilation is available without needing additional packages.
The functionality has been moved to the Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation package.
The following APIs were previously available in Microsoft.AspNetCore.Mvc.Razor.RazorViewEngineOptions
to support runtime compilation. The APIs are now available via
Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.MvcRazorRuntimeCompilationOptions
.
RazorViewEngineOptions.FileProviders
is now MvcRazorRuntimeCompilationOptions.FileProviders
RazorViewEngineOptions.AdditionalCompilationReferences
is now MvcRazorRuntimeCompilationOptions.AdditionalReferencePaths
In addition, Microsoft.AspNetCore.Mvc.Razor.RazorViewEngineOptions.AllowRecompilingViewsOnFileChange
has been removed. Recompilation on file changes is enabled by default by referencing the Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation
package.
This change was necessary to remove the ASP.NET Core shared framework dependency on Roslyn.
Apps that require runtime compilation or recompilation of Razor files should take the following steps:
Add a reference to the Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation
package.
Update the project's Startup.ConfigureServices
method to include a call to AddRazorRuntimeCompilation
. For example:
services.AddMvc()
.AddRazorRuntimeCompilation();
ASP.NET Core
Microsoft.AspNetCore.Mvc.Razor.RazorViewEngineOptions
Obsolete APIs for configuring session cookies were removed. For more information, see aspnet/Announcements#257.
3.0
This change enforces consistency across APIs for configuring features that use cookies.
Migrate usage of the removed APIs to their newer replacements. Consider the following example in Startup.ConfigureServices
:
public void ConfigureServices(ServiceCollection services)
{
services.AddSession(options =>
{
// Removed obsolete APIs
options.CookieName = "SessionCookie";
options.CookieDomain = "contoso.com";
options.CookiePath = "/";
options.CookieHttpOnly = true;
options.CookieSecure = CookieSecurePolicy.Always;
// new API
options.Cookie.Name = "SessionCookie";
options.Cookie.Domain = "contoso.com";
options.Cookie.Path = "/";
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
}
ASP.NET Core
Starting in ASP.NET Core 3.0, the ASP.NET Core shared framework (Microsoft.AspNetCore.App
) only contains first-party assemblies that are fully developed, supported, and serviceable by Microsoft.
Think of the change as the redefining of boundaries for the ASP.NET Core "platform." The shared framework will be source-buildable by anybody via GitHub and will continue to offer the existing benefits of .NET Core shared frameworks to your apps. Some benefits include smaller deployment size, centralized patching, and faster startup time.
As part of the change, some notable breaking changes are introduced in Microsoft.AspNetCore.App
.
3.0
Projects referenced Microsoft.AspNetCore.App
via a <PackageReference>
element in the project file.
Additionally, Microsoft.AspNetCore.App
contained the following subcomponents:
Newtonsoft.Json
)Microsoft.EntityFrameworkCore.
)Microsoft.CodeAnalysis
)A reference to Microsoft.AspNetCore.App
no longer requires a <PackageReference>
element in the project file. The .NET Core SDK supports a new element called
<FrameworkReference>
, which replaces the use of <PackageReference>
.
For more information, see dotnet/aspnetcore#3612.
Entity Framework Core ships as NuGet packages. This change aligns the shipping model with all other data access libraries on .NET. It provides Entity Framework Core the simplest path to continue innovating while supporting the various .NET platforms. The move of Entity Framework Core out of the shared framework has no impact on its status as a Microsoft-developed, supported, and serviceable library. The .NET Core support policy continues to cover it.
Json.NET and Entity Framework Core continue to work with ASP.NET Core. They won't, however, be included in the shared framework.
For more information, see The future of JSON in .NET Core 3.0. Also see the complete list of binaries removed from the shared framework.
This change simplifies the consumption of Microsoft.AspNetCore.App
and reduces the duplication between NuGet packages and shared frameworks.
For more information on the motivation for this change, see this blog post.
Starting with ASP.NET Core 3.0, it is no longer necessary for projects to consume assemblies in Microsoft.AspNetCore.App
as NuGet packages. To simplify the targeting and usage of the ASP.NET Core shared framework, many NuGet packages shipped since ASP.NET Core 1.0 are no longer produced. The APIs those packages provide are still available to apps by using a <FrameworkReference>
to Microsoft.AspNetCore.App
. Common API examples include Kestrel, MVC, and Razor.
This change doesn't apply to all binaries referenced via Microsoft.AspNetCore.App
in ASP.NET Core 2.x. Notable exceptions include:
Microsoft.Extensions
libraries that continue to target .NET Standard are available as NuGet packages (see https://github.com/dotnet/extensions).Microsoft.AspNetCore.App
. For example, the following components are available as NuGet packages:
For more information, see Stop producing packages for shared framework assemblies in 3.0. For discussion, see dotnet/aspnetcore#3757.
ASP.NET Core
Starting in ASP.NET Core 3.0, the Microsoft.AspNetCore.All
metapackage and the matching Microsoft.AspNetCore.All
shared framework are no longer produced. This package is available in ASP.NET Core 2.2 and will continue to receive servicing updates in ASP.NET Core 2.1.
3.0
Apps could use the Microsoft.AspNetCore.All
metapackage to target the Microsoft.AspNetCore.All
shared framework on .NET Core.
.NET Core 3.0 doesn't include a Microsoft.AspNetCore.All
shared framework.
The Microsoft.AspNetCore.All
metapackage included a large number of external dependencies.
Migrate your project to use the Microsoft.AspNetCore.App
framework. Components that were previously available in Microsoft.AspNetCore.All
are still available on NuGet. Those components are now deployed with your app instead of being included in the shared framework.
ASP.NET Core
None
The HandshakeProtocol.SuccessHandshakeData field was removed and replaced with a helper method that generates a successful handshake response given a specific IHubProtocol
.
3.0
HandshakeProtocol.SuccessHandshakeData
was a public static ReadOnlyMemory<byte>
field.
HandshakeProtocol.SuccessHandshakeData
has been replaced by a static
GetSuccessfulHandshake(IHubProtocol protocol)
method that returns a ReadOnlyMemory<byte>
based on the specified protocol.
Additional fields were added to the handshake response that are non-constant and change depending on the selected protocol.
None. This type isn't designed for use from user code. It's public
, so it can be shared between the SignalR server and client. It may also be used by customer SignalR clients written in .NET. Users of SignalR shouldn't be affected by this change.
ASP.NET Core
HandshakeProtocol.SuccessHandshakeData
The ResetSendPing
and ResetTimeout
methods were removed from the SignalR HubConnection
API. These methods were originally intended only for internal use but were made public in ASP.NET Core 2.2. These methods won't be available starting in the ASP.NET Core 3.0 Preview 4 release. For discussion, see dotnet/aspnetcore#8543.
3.0
APIs were available.
APIs are removed.
These methods were originally intended only for internal use but were made public in ASP.NET Core 2.2.
Don't use these methods.
ASP.NET Core
SignalR's HubConnectionContext
constructors changed to accept an options type, rather than multiple parameters, to future-proof adding options. This change replaces two constructors with a single constructor that accepts an options type.
3.0
HubConnectionContext
has two constructors:
public HubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory);
public HubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory, TimeSpan clientTimeoutInterval);
The two constructors were removed and replaced with one constructor:
public HubConnectionContext(ConnectionContext connectionContext, HubConnectionContextOptions contextOptions, ILoggerFactory loggerFactory)
The new constructor uses a new options object. Consequently, the features of HubConnectionContext
can be expanded in the future without making more constructors and breaking changes.
Instead of using the following constructor:
HubConnectionContext connectionContext = new HubConnectionContext(
connectionContext,
keepAliveInterval: TimeSpan.FromSeconds(15),
loggerFactory,
clientTimeoutInterval: TimeSpan.FromSeconds(15));
Use the following constructor:
HubConnectionContextOptions contextOptions = new HubConnectionContextOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(15),
ClientTimeoutInterval = TimeSpan.FromSeconds(15)
};
HubConnectionContext connectionContext = new HubConnectionContext(connectionContext, contextOptions, loggerFactory);
ASP.NET Core
In ASP.NET Core 3.0 Preview 7, the SignalR JavaScript client package name changed from @aspnet/signalr
to @microsoft/signalr
. The name change reflects the fact that SignalR is useful in more than just ASP.NET Core apps, thanks to the Azure SignalR Service.
To react to this change, change references in your package.json files, require
statements, and ECMAScript import
statements. No API will change as part of this rename.
For discussion, see dotnet/aspnetcore#11637.
3.0
The client package was named @aspnet/signalr
.
The client package is named @microsoft/signalr
.
The name change clarifies that SignalR is useful beyond ASP.NET Core apps, thanks to the Azure SignalR Service.
Switch to the new package @microsoft/signalr
.
ASP.NET Core
None
The methods UseConnections
and UseSignalR
and the classes ConnectionsRouteBuilder
and HubRouteBuilder
are marked as obsolete in ASP.NET Core 3.0.
3.0
SignalR hub routing was configured using UseSignalR
or UseConnections
.
The old way of configuring routing has been obsoleted and replaced with endpoint routing.
Middleware is being moved to the new endpoint routing system. The old way of adding middleware is being obsoleted.
Replace UseSignalR
with UseEndpoints
:
Old code:
app.UseSignalR(routes =>
{
routes.MapHub<SomeHub>("/path");
});
New code:
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<SomeHub>("/path");
});
ASP.NET Core
The contents of the following NuGet packages have all been unnecessary since ASP.NET Core 2.1. Consequently, the following packages are being marked as obsolete:
For the same reason, the following npm modules are being marked as deprecated:
The preceding packages and npm modules will later be removed in .NET 5.
3.0
The deprecated packages and npm modules were intended to integrate ASP.NET Core with various Single-Page App (SPA) frameworks. Such frameworks include Angular, React, and React with Redux.
A new integration mechanism exists in the Microsoft.AspNetCore.SpaServices.Extensions NuGet package. The package remains the basis of the Angular and React project templates since ASP.NET Core 2.1.
ASP.NET Core supports integration with various Single-Page App (SPA) frameworks, including Angular, React, and React with Redux. Initially, integration with these frameworks was accomplished with ASP.NET Core-specific components that handled scenarios like server-side prerendering and integration with Webpack. As time went on, industry standards changed. Each of the SPA frameworks released their own standard command-line interfaces. For example, Angular CLI and create-react-app.
When ASP.NET Core 2.1 was released in May 2018, the team responded to the change in standards. A newer and simpler way to integrate with the SPA frameworks' own toolchains was provided. The new integration mechanism exists in the package Microsoft.AspNetCore.SpaServices.Extensions
and remains the basis of the Angular and React project templates since ASP.NET Core 2.1.
To clarify that the older ASP.NET Core-specific components are irrelevant and not recommended:
If you're using these packages, update your apps to use the functionality:
Microsoft.AspNetCore.SpaServices.Extensions
package.To enable features like server-side prerendering and hot module reload, see the documentation for the corresponding SPA framework. The functionality in Microsoft.AspNetCore.SpaServices.Extensions
is not obsolete and will continue to be supported.
ASP.NET Core
Microsoft.AspNetCore.NodeServices.HostingModels.INodeInstance
Microsoft.AspNetCore.NodeServices.HostingModels.NodeInvocationException
Microsoft.AspNetCore.NodeServices.HostingModels.NodeInvocationInfo
Microsoft.AspNetCore.NodeServices.HostingModels.NodeServicesOptionsExtensions
Microsoft.AspNetCore.NodeServices.HostingModels.OutOfProcessNodeInstance
Microsoft.AspNetCore.SpaServices.Prerendering.ISpaPrerenderer
Microsoft.AspNetCore.SpaServices.Prerendering.ISpaPrerendererBuilder
Microsoft.AspNetCore.SpaServices.Prerendering.JavaScriptModuleExport
Microsoft.AspNetCore.SpaServices.Prerendering.PrerenderTagHelper
Microsoft.AspNetCore.SpaServices.Prerendering.RenderToStringResult
Microsoft.AspNetCore.SpaServices.Webpack.WebpackDevMiddlewareOptions
Microsoft.Extensions.DependencyInjection.NodeServicesServiceCollectionExtensions
Microsoft.Extensions.DependencyInjection.PrerenderingServiceCollectionExtensions
Microsoft.AspNetCore.SpaServices and Microsoft.AspNetCore.NodeServices won't display console logs unless logging is configured.
3.0
Microsoft.AspNetCore.SpaServices
and Microsoft.AspNetCore.NodeServices
used to automatically create a console logger when logging isn't configured.
Microsoft.AspNetCore.SpaServices
and Microsoft.AspNetCore.NodeServices
won't display console logs unless logging is configured.
There's a need to align with how other ASP.NET Core packages implement logging.
If the old behavior is required, to configure console logging, add services.AddLogging(builder => builder.AddConsole())
to your Setup.ConfigureServices
method.
ASP.NET Core
None
Starting with ASP.NET Core 3.0, .NET Framework is an unsupported target framework.
.NET Framework 4.8 is the last major version of .NET Framework. New ASP.NET Core apps should be built on .NET Core. Starting with the .NET Core 3.0 release, you can think of ASP.NET Core 3.0 as being part of .NET Core.
Customers using ASP.NET Core with .NET Framework can continue in a fully supported fashion using the 2.1 LTS release. Support and servicing for 2.1 continues until at least August 21, 2021. This date is three years after declaration of the LTS release per the .NET Support Policy. Support for ASP.NET Core 2.1 packages on .NET Framework will extend indefinitely, similar to the servicing policy for other package-based ASP.NET frameworks.
For more information about porting from .NET Framework to .NET Core, see Porting to .NET Core.
Microsoft.Extensions
packages (such as logging, dependency injection, and configuration) and Entity Framework Core aren't affected. They'll continue to support .NET Standard.
For more information on the motivation for this change, see the original blog post.
3.0
ASP.NET Core apps could run on either .NET Core or .NET Framework.
ASP.NET Core apps can only be run on .NET Core.
Take one of the following actions:
ASP.NET Core
None
Many of the APIs that return versions in .NET Core now return the product version rather than the file version.
In .NET Core 2.2 and previous versions, methods such as Environment.Version, RuntimeInformation.FrameworkDescription, and the file properties dialog for .NET Core assemblies reflect the file version. Starting with .NET Core 3.0, they reflect the product version.
The following figure illustrates the difference in version information for the System.Runtime.dll assembly for .NET Core 2.2 (on the left) and .NET Core 3.0 (on the right) as displayed by the Windows Explorer file properties dialog.
3.0
None. This change should make version detection intuitive rather than obtuse.
Core .NET libraries
Custom EncoderFallbackBuffer instances cannot fall back recursively. The implementation of EncoderFallbackBuffer.GetNextChar() must result in a character sequence that is convertible to the destination encoding. Otherwise, an exception occurs.
During a character-to-byte transcoding operation, the runtime detects ill-formed or nonconvertible UTF-16 sequences and provides those characters to the EncoderFallbackBuffer.Fallback method. The Fallback
method determines which characters should be substituted for the original nonconvertible data, and these characters are drained by calling EncoderFallbackBuffer.GetNextChar in a loop.
The runtime then attempts to transcode these substitution characters to the target encoding. If this operation succeeds, the runtime continues transcoding from where it left off in the original input string.
Previously, custom implementations of EncoderFallbackBuffer.GetNextChar() can return character sequences that are not convertible to the destination encoding. If the substituted characters cannot be transcoded to the target encoding, the runtime invokes the EncoderFallbackBuffer.Fallback method once again with the substitution characters, expecting the EncoderFallbackBuffer.GetNextChar() method to return a new substitution sequence. This process continues until the runtime eventually sees a well-formed, convertible substitution, or until a maximum recursion count is reached.
Starting with .NET Core 3.0, custom implementations of EncoderFallbackBuffer.GetNextChar() must return character sequences that are convertible to the destination encoding. If the substituted characters cannot be transcoded to the target encoding, an ArgumentException is thrown. The runtime will no longer make recursive calls into the EncoderFallbackBuffer instance.
This behavior only applies when all three of the following conditions are met:
3.0
Most developers needn't take any action.
If an application uses a custom EncoderFallback and EncoderFallbackBuffer class, ensure the implementation of EncoderFallbackBuffer.Fallback populates the fallback buffer with well-formed UTF-16 data that is directly convertible to the target encoding when the Fallback method is first invoked by the runtime.
Core .NET libraries
Floating-point parsing and formatting behavior (by the Double and Single types) are now IEEE-compliant. This ensures that the behavior of floating-point types in .NET matches that of other IEEE-compliant languages. For example, double.Parse("SomeLiteral")
should always match what C# produces for double x = SomeLiteral
.
In .NET Core 2.2 and earlier versions, formatting with Double.ToString and Single.ToString, and parsing with Double.Parse, Double.TryParse, Single.Parse, and Single.TryParse are not IEEE-compliant. As a result, it's impossible to guarantee that a value will roundtrip with any supported standard or custom format string. For some inputs, the attempt to parse a formatted value can fail, and for others, the parsed value doesn't equal the original value.
Starting with .NET Core 3.0, floating-point parsing and formatting operations are IEEE 754-compliant.
The following table shows two code snippets and how the output changes between .NET Core 2.2 and .NET Core 3.1.
Code snippet | Output on .NET Core 2.2 | Output on .NET Core 3.1 |
---|---|---|
Console.WriteLine((-0.0).ToString()); |
0 | -0 |
var value = -3.123456789123456789; Console.WriteLine(value == double.Parse(value.ToString())); |
False |
True |
For more information, see the Floating-point parsing and formatting improvements in .NET Core 3.0 blog post.
3.0
The Potential impact to existing code section of the Floating-point parsing and formatting improvements in .NET Core 3.0 blog post suggests some changes you can make to your code if you want to maintain the previous behavior.
Core .NET libraries
The floating-point parsing methods no longer throw an OverflowException or return false
when they parse a string whose numeric value is outside the range of the Single or Double floating-point type.
In .NET Core 2.2 and earlier versions, the Double.Parse and Single.Parse methods throw an OverflowException for values that outside the range of their respective type. The Double.TryParse and Single.TryParse methods return false
for the string representations of out-of-range numeric values.
Starting with .NET Core 3.0, the Double.Parse, Double.TryParse, Single.Parse, and Single.TryParse methods no longer fail when parsing out-of-range numeric strings. Instead, the Double parsing methods return Double.PositiveInfinity for values that exceed Double.MaxValue, and they return Double.NegativeInfinity for values that are less than Double.MinValue. Similarly, the Single parsing methods return Single.PositiveInfinity for values that exceed Single.MaxValue, and they return Single.NegativeInfinity for values that are less than Single.MinValue.
This change was made for improved IEEE 754:2008 compliance.
3.0
This change can affect your code in either of two ways:
Your code depends on the handler for the OverflowException to execute when an overflow occurs. In this case, you should remove the catch
statement and place any necessary code in an If
statement that tests whether Double.IsInfinity or Single.IsInfinity is true
.
Your code assumes that floating-point values are not Infinity
. In this case, you should add the necessary code to check for floating-point values of PositiveInfinity
and NegativeInfinity
.
Core .NET libraries
The InvalidAsynchronousStateException class has been moved.
In .NET Core 2.2 and earlier versions, the InvalidAsynchronousStateException class is found in the System.ComponentModel.TypeConverter assembly.
Starting with .NET Core 3.0, it is found in the System.ComponentModel.Primitives assembly.
3.0
This change only affects applications that use reflection to load the InvalidAsynchronousStateException by calling a method such as Assembly.GetType or an overload of Activator.CreateInstance that assumes the type is in a particular assembly. If that is the case, update the assembly referenced in the method call to reflect the type's new assembly location.
Core .NET libraries
None.
When the UTF8Encoding class encounters an ill-formed UTF-8 byte sequence during a byte-to-character transcoding operation, it replaces that sequence with a '�' (U+FFFD REPLACEMENT CHARACTER) character in the output string. .NET Core 3.0 differs from previous versions of .NET Core and the .NET Framework by following the Unicode best practice for performing this replacement during the transcoding operation.
This is part of a larger effort to improve UTF-8 handling throughout .NET, including by the new System.Text.Unicode.Utf8 and System.Text.Rune types. The UTF8Encoding type was given improved error handling mechanics so that it produces output consistent with the newly introduced types.
Starting with .NET Core 3.0, when transcoding bytes to characters, the UTF8Encoding class performs character substitution based on Unicode best practices. The substitution mechanism used is described by The Unicode Standard, Version 12.0, Sec. 3.9 (PDF) in the heading titled U+FFFD Substitution of Maximal Subparts.
This behavior only applies when the input byte sequence contains ill-formed UTF-8 data. Additionally, if the UTF8Encoding instance has been constructed with throwOnInvalidBytes: true
, the UTF8Encoding
instance will continue to throw on invalid input rather than perform U+FFFD replacement. For more information about the UTF8Encoding
constructor, see UTF8Encoding(Boolean, Boolean).
The following table illustrates the impact of this change with an invalid 3-byte input:
Ill-formed 3-byte input | Output before .NET Core 3.0 | Output starting with .NET Core 3.0 |
---|---|---|
[ ED A0 90 ] |
[ FFFD FFFD ] (2-character output) |
[ FFFD FFFD FFFD ] (3-character output) |
The 3-char output is the preferred output, according to Table 3-9 of the previously linked Unicode Standard PDF.
3.0
No action is required on the part of the developer.
Core .NET libraries
The TypeDescriptionProviderAttribute class has been moved.
In .NET Core 2.2 and earlier versions, The TypeDescriptionProviderAttribute class is found in the System.ComponentModel.TypeConverter assembly.
Starting with .NET Core 3.0, it is found in the System.ObjectModel assembly.
3.0
This change only affects applications that use reflection to load the TypeDescriptionProviderAttribute type by calling a method such as Assembly.GetType or an overload of Activator.CreateInstance that assumes the type is in a particular assembly. If that is the case, the assembly referenced in the method call should be updated to reflect the type's new assembly location.
Windows Forms
None.
Zip archives list both compressed size and uncompressed size in the central directory and local header. The entry data itself also indicates its size. In .NET Core 2.2 and earlier versions, these values were never checked for consistency. Starting with .NET Core 3.0, they now are.
In .NET Core 2.2 and earlier versions, ZipArchiveEntry.Open() succeeds even if the local header disagrees with the central header of the zip file. Data is decompressed until the end of the compressed stream is reached, even if its length exceeds the uncompressed file size listed in the central directory/local header.
Starting with .NET Core 3.0, the ZipArchiveEntry.Open() method checks that local header and central header agree on compressed and uncompressed sizes of an entry. If they do not, the method throws an InvalidDataException if the archive's local header and/or data descriptor list sizes that disagree with the central directory of the zip file. When reading an entry, decompressed data is truncated to the uncompressed file size listed in the header.
This change was made to ensure that a ZipArchiveEntry correctly represents the size of its data and that only that amount of data is read.
3.0
Repackage any zip archive that exhibits these problems.
Core .NET libraries
Starting in .NET Core 3.0, an exception is thrown when you attempt to set a value on a static, InitOnly field by calling System.Reflection.FieldInfo.SetValue.
In .NET Framework and versions of .NET Core prior to 3.0, you could set the value of a static field that's constant after it is initialized (readonly in C#) by calling System.Reflection.FieldInfo.SetValue. However, setting such a field in this way resulted in unpredictable behavior based on the target framework and optimization settings.
In .NET Core 3.0 and later versions, when you call SetValue on a static, InitOnly field, a System.FieldAccessException exception is thrown.
Tip
An InitOnly field is one that can only be set at the time it's declared or in the constructor for the containing class. In other words, it's constant after it is initialized.
3.0
Initialize static, InitOnly fields in a static constructor. This applies to both dynamic and non-dynamic types.
Alternatively, you can remove the FieldAttributes.InitOnly attribute from the field, and then call FieldInfo.SetValue.
Core .NET libraries
When calling an extension method that takes an IEnumerable<T>
on a GroupCollection, you must disambiguate the type using a cast.
Starting in .NET Core 3.0, System.Text.RegularExpressions.GroupCollection implements IEnumerable<KeyValuePair<String,Group>>
in addition to the other types it implements, including IEnumerable<Group>
. This results in ambiguity when calling an extension method that takes an IEnumerable<T>. If you call such an extension method on a GroupCollection instance, for example, Enumerable.Count, you'll see the following compiler error:
CS1061: 'GroupCollection' does not contain a definition for 'Count' and no accessible extension method 'Count' accepting a first argument of type 'GroupCollection' could be found (are you missing a using directive or an assembly reference?)
In previous versions of .NET, there was no ambiguity and no compiler error.
3.0
This was an unintentional breaking change. Because it has been like this for some time, we don't plan to revert it. In addition, such a change would itself be breaking.
For GroupCollection instances, disambiguate calls to extension methods that accept an IEnumerable<T>
with a cast.
// Without a cast - causes CS1061.
match.Groups.Count(_ => true)
// With a disambiguating cast.
((IEnumerable<Group>)m.Groups).Count(_ => true);
Core .NET libraries
Any extension method that accepts an IEnumerable<T> is affected. For example:
System.Linq.Enumerable
methods, for example, System.Linq.Enumerable.CountRoot certificates on Linux and other Unix-like systems (but not macOS) can be presented in two forms: the standard BEGIN CERTIFICATE
PEM header, and the OpenSSL-specific BEGIN TRUSTED CERTIFICATE
PEM header. The latter syntax allows for additional configuration that has caused compatibility issues with .NET Core's System.Security.Cryptography.X509Certificates.X509Chain class. BEGIN TRUSTED CERTIFICATE
root certificate contents are no longer loaded by the chain engine starting in .NET Core 3.0.
Previously, both the BEGIN CERTIFICATE
and BEGIN TRUSTED CERTIFICATE
syntaxes were used to populate the root trust list. If the BEGIN TRUSTED CERTIFICATE
syntax was used and additional options were specified in the file, X509Chain may have reported that the chain trust was explicitly disallowed (X509ChainStatusFlags.ExplicitDistrust). However, if the certificate was also specified with the BEGIN CERTIFICATE
syntax in a previously loaded file, the chain trust was allowed.
Starting in .NET Core 3.0, BEGIN TRUSTED CERTIFICATE
contents are no longer read. If the certificate is not also specified via a standard BEGIN CERTIFICATE
syntax, the X509Chain reports that the root is not trusted (X509ChainStatusFlags.UntrustedRoot).
3.0
Most applications are unaffected by this change, but applications that cannot see both root certificate sources because of permissions problems may experience unexpected UntrustedRoot
errors after upgrading.
Many Linux distributions (or distros) write root certificates into two locations: a one-certificate-per-file directory, and a one-file concatenation. On some distros, the one-certificate-per-file directory uses the BEGIN TRUSTED CERTIFICATE
syntax while the file concatenation uses the standard BEGIN CERTIFICATE
syntax. Ensure that any custom root certificates are added as BEGIN CERTIFICATE
in at least one of these locations, and that both locations can be read by your application.
The typical directory is /etc/ssl/certs/ and the typical concatenated file is /etc/ssl/cert.pem. Use the command openssl version -d
to determine the platform-specific root, which may differ from /etc/ssl/. For example, on Ubuntu 18.04, the directory is /usr/lib/ssl/certs/ and the file is /usr/lib/ssl/cert.pem. However, /usr/lib/ssl/certs/ is a symlink to /etc/ssl/certs/ and /usr/lib/ssl/cert.pem does not exist.
$ openssl version -d
OPENSSLDIR: "/usr/lib/ssl"
$ ls -al /usr/lib/ssl
total 12
drwxr-xr-x 3 root root 4096 Dec 12 17:10 .
drwxr-xr-x 73 root root 4096 Feb 20 15:18 ..
lrwxrwxrwx 1 root root 14 Mar 27 2018 certs -> /etc/ssl/certs
drwxr-xr-x 2 root root 4096 Dec 12 17:10 misc
lrwxrwxrwx 1 root root 20 Nov 12 16:58 openssl.cnf -> /etc/ssl/openssl.cnf
lrwxrwxrwx 1 root root 16 Mar 27 2018 private -> /etc/ssl/private
Cryptography
The default symmetric encryption algorithm used by EnvelopedCms
has changed from TripleDES to AES-256.
In previous versions, when EnvelopedCms is used to encrypt data without specifying a symmetric encryption algorithm via a constructor overload, the data is encrypted with the TripleDES/3DES/3DEA/DES3-EDE algorithm.
Starting with .NET Core 3.0 (via version 4.6.0 of the System.Security.Cryptography.Pkcs NuGet package), the default algorithm has been changed to AES-256 for algorithm modernization and to improve the security of default options. If a message recipient certificate has a (non-EC) Diffie-Hellman public key, the encryption operation may fail with a CryptographicException due to limitations in the underlying platform.
In the following sample code, the data is encrypted with TripleDES if running on .NET Core 2.2 or earlier. If running on .NET Core 3.0 or later, it's encrypted with AES-256.
EnvelopedCms cms = new EnvelopedCms(content);
cms.Encrypt(recipient);
return cms.Encode();
3.0
If you are negatively impacted by the change, you can restore TripleDES encryption by explicitly specifying the encryption algorithm identifier in an EnvelopedCms constructor that includes a parameter of type AlgorithmIdentifier, such as:
Oid tripleDesOid = new Oid("1.2.840.113549.3.7", null);
AlgorithmIdentifier tripleDesIdentifier = new AlgorithmIdentifier(tripleDesOid);
EnvelopedCms cms = new EnvelopedCms(content, tripleDesIdentifier);
cms.Encrypt(recipient);
return cms.Encode();
Cryptography
The minimum size for generating new RSA keys on Linux has increased from 384-bit to 512-bit.
Starting with .NET Core 3.0, the minimum legal key size reported by the LegalKeySizes
property on RSA instances from RSA.Create, RSAOpenSsl, and RSACryptoServiceProvider on Linux has increased from 384 to 512.
As a result, in .NET Core 2.2 and earlier versions, a method call such as RSA.Create(384)
succeeds. In .NET Core 3.0 and later versions, the method call RSA.Create(384)
throws an exception indicating the size is too small.
This change was made because OpenSSL, which performs the cryptographic operations on Linux, raised its minimum between versions 1.0.2 and 1.1.0. .NET Core 3.0 prefers OpenSSL 1.1.x to 1.0.x, and the minimum reported version was raised to reflect this new higher dependency limitation.
3.0
If you call any of the affected APIs, ensure that the size of any generated keys is not less than the provider minimum.
Note
384-bit RSA is already considered insecure (as is 512-bit RSA). Modern recommendations, such as NIST Special Publication 800-57 Part 1 Revision 4, suggest 2048-bit as the minimum size for newly generated keys.
Cryptography
.NET Core for Linux, which works across multiple Linux distributions, can support both OpenSSL 1.0.x and OpenSSL 1.1.x. .NET Core 2.1 and .NET Core 2.2 look for 1.0.x first, then fall back to 1.1.x; .NET Core 3.0 looks for 1.1.x first. This change was made to add support for new cryptographic standards.
This change may impact libraries or applications that do platform interop with the OpenSSL-specific interop types in .NET Core.
In .NET Core 2.2 and earlier versions, the runtime prefers loading OpenSSL 1.0.x over 1.1.x. This means that the IntPtr and SafeHandle types for interop with OpenSSL are used with libcrypto.so.1.0.0 / libcrypto.so.1.0 / libcrypto.so.10 by preference.
Starting with .NET Core 3.0, the runtime prefers loading OpenSSL 1.1.x over OpenSSL 1.0.x, so the IntPtr and SafeHandle types for interop with OpenSSL are used with libcrypto.so.1.1 / libcrypto.so.11 / libcrypto.so.1.1.0 / libcrypto.so.1.1.1 by preference. As a result, libraries and applications that interoperate with OpenSSL directly may have incompatible pointers with the .NET Core-exposed values when upgrading from .NET Core 2.1 or .NET Core 2.2.
3.0
Libraries and applications that do direct operations with OpenSSL need to be careful to ensure they are using the same version of OpenSSL as the .NET Core runtime.
All libraries or applications that use IntPtr or SafeHandle values from the .NET Core cryptographic types directly with OpenSSL should compare the version of the library they use with the new SafeEvpPKeyHandle.OpenSslVersion property to ensure the pointers are compatible.
Cryptography
The CryptoStream.Dispose method, which is used to finish CryptoStream
operations, no longer attempts to transform the final block when reading.
In previous .NET versions, if a user performed an incomplete read when using CryptoStream in Read mode, the Dispose method could throw an exception (for example, when using AES with padding). The exception was thrown because the final block was attempted to be transformed but the data was incomplete.
In .NET Core 3.0 and later versions, Dispose no longer tries to transform the final block when reading, which allows for incomplete reads.
This change enables incomplete reads from the crypto stream when a network operation is canceled, without the need to catch an exception.
3.0
Most apps should not be affected by this change.
If your application previously caught an exception in case of an incomplete read, you can delete that catch
block.
If your app used transforming of the final block in hashing scenarios, you might need to ensure that the entire stream is read before it's disposed.
Cryptography
Entity Framework Core breaking changes
.NET Core 2.2 and earlier versions depend on the default ICU behavior, which maps the "C" locale to the en_US_POSIX locale. The en_US_POSIX locale has an undesirable collation behavior, because it doesn't support case-insensitive string comparisons. Because some Linux distributions set the "C" locale as the default locale, users were experiencing unexpected behavior.
Starting with .NET Core 3.0, the "C" locale mapping has changed to use the Invariant locale instead of en_US_POSIX. The "C" locale to Invariant mapping is also applied to Windows for consistency.
Mapping "C" to en_US_POSIX culture caused customer confusion, because en_US_POSIX doesn't support case insensitive sorting/searching string operations. Because the "C" locale is used as a default locale in some of the Linux distros, customers experienced this undesired behavior on these operating systems.
3.0
Nothing specific more than the awareness of this change. This change affects only applications that use the "C" locale mapping.
Globalization
All collation and culture APIs are affected by this change.
Starting in .NET Core 3.0, in the default case, MSBuild generates a different manifest file name for resource files.
3.0
Prior to .NET Core 3.0, if no LogicalName
, ManifestResourceName
, or DependentUpon
metadata was specified for an EmbeddedResource
item in the project file, MSBuild generated a manifest file name in the pattern <RootNamespace>.<ResourceFilePathFromProjectRoot>.resources
. If RootNamespace
is not defined in the project file, it defaults to the project name. For example, the generated manifest name for a resource file named Form1.resx in the root project directory was MyProject.Form1.resources.
Starting in .NET Core 3.0, if a resource file is colocated with a source file of the same name (for example, Form1.resx and Form1.cs), MSBuild uses type information from the source file to generate the manifest file name in the pattern <Namespace>.<ClassName>.resources
. The namespace and class name are extracted from the first type in the colocated source file. For example, the generated manifest name for a resource file named Form1.resx that's colocated with a source file named Form1.cs is MyNamespace.Form1.resources. The key thing to note is that the first part of the file name is different to prior versions of .NET Core (MyNamespace instead of MyProject).
Note
If you have LogicalName
, ManifestResourceName
, or DependentUpon
metadata specified on an EmbeddedResource
item in the project file, then this change does not affect that resource file.
This breaking change was introduced with the addition of the EmbeddedResourceUseDependentUponConvention
property to .NET Core projects. By default, resource files aren't explicitly listed in a .NET Core project file, so they have no DependentUpon
metadata to specify how to name the generated .resources file. When EmbeddedResourceUseDependentUponConvention
is set to true
, which is the default, MSBuild looks for a colocated source file and extracts a namespace and class name from that file. If you set EmbeddedResourceUseDependentUponConvention
to false
, MSBuild generates the manifest name according to the previous behavior, which combines RootNamespace
and the relative file path.
In most cases, no action is required on the part of the developer, and your app should continue to work. However, if this change breaks your app, you can either:
Change your code to expect the new manifest name.
Opt out of the new naming convention by setting EmbeddedResourceUseDependentUponConvention
to false
in your project file.
<PropertyGroup>
<EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention>
</PropertyGroup>
MSBuild
N/A
The default value of the System.Net.Http.HttpRequestMessage.Version property has changed from 2.0 to 1.1.
3.0
In .NET Core 1.0 through 2.0, the default value of the System.Net.Http.HttpRequestMessage.Version property is 1.1. Starting with .NET Core 2.1, it was changed to 2.1.
Starting with .NET Core 3.0, the default version number returned by the System.Net.Http.HttpRequestMessage.Version property is once again 1.1.
Update your code if it depends on the System.Net.Http.HttpRequestMessage.Version property returning a default value of 2.0.
Networking
.NET Core 3.0 introduced a change in how text editor controls create a System.Windows.DataObject when dragging text to another control. The change disabled autoconversion, causing the operation to keep the data as DataFormats.Text or DataFormats.UnicodeText instead of converting it to DataFormats.StringFormat.
.NET Core 3.0
Windows Presentation Foundation
The data type on System.Windows.DataObject when dragging text from a text editor control was DataFormats.StringFormat.
The data type on System.Windows.DataObject when dragging text from a text editor control is DataFormats.Text or DataFormats.UnicodeText.
This change is a behavioral change.
The change was unintentional.
This change was reverted in .NET 7. Upgrade to .NET 7 or later.
.NET feedback
.NET is an open source project. Select a link to provide feedback:
Training
Module
Secure a .NET web app with the ASP.NET Core Identity framework - Training
Learn how to add authentication and authorization to a .NET web app using the ASP.NET Core Identity framework.