--- title: What's new in ASP.NET Core 6.0 author: rick-anderson description: Learn about the new features in ASP.NET Core 6.0. ms.author: riande ms.custom: mvc ms.date: 10/29/2021 uid: aspnetcore-6.0 --- # What's new in ASP.NET Core 6.0 This article highlights the most significant changes in ASP.NET Core 6.0 with links to relevant documentation. ## ASP.NET Core MVC and Razor improvements ## Minimal APIs Minimal APIs are architected to create HTTP APIs with minimal dependencies. They are ideal for microservices and apps that want to include only the minimum files, features, and dependencies in ASP.NET Core. For more information, see: * * [Differences between minimal APIs and APIs with controllers](xref:tutorials/min-web-api?view=aspnetcore-6.0#differences-between-minimal-apis-and-apis-with-controllers) * * ## SignalR ### Long running activity tag for SignalR connections SignalR uses the new to add an `http.long_running` tag to the request activity. `IHttpActivityFeature.Activity` is used by [APM services](https://wikipedia.org/wiki/Application_performance_management) like [Azure Monitor Application Insights](/azure/azure-monitor/azure-monitor-app-hub) to filter SignalR requests from creating long running request alerts. ### SignalR performance improvements * Allocate [HubCallerClients](https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/server/Core/src/Internal/HubCallerClients.cs) once per connection instead of every hub method call. * Avoid closure allocation in SignalR `DefaultHubDispatcher.Invoke`. State is passed to a local static function via parameters to avoid a closure allocation. For more information, see [this GitHub pull request](https://github.com/dotnet/aspnetcore/pull/31641). * Allocate a single per stream instead of per stream item in server-to-client streaming. For more information, see [this GitHub pull request](https://github.com/dotnet/aspnetcore/pull/31660). ## Razor compiler ### Razor compiler updated to use source generators The Razor compiler is now based on [C# source generators](/dotnet/csharp/roslyn-sdk/source-generators-overview). Source generators run during compilation and inspect what is being compiled to produce additional files that are compiled along with the rest of the project. Using source generators simplifies the Razor compiler and significantly speeds up build times. ### Razor compiler no longer produces a separate Views assembly The Razor compiler previously utilized a two-step compilation process that produced a separate Views assembly that contained the generated views and pages (`.cshtml` files) defined in the app. The generated types were public and under the `AspNetCore` namespace. The updated Razor compiler builds the views and pages types into the main project assembly. These types are now generated by default as internal sealed in the `AspNetCoreGeneratedDocument` namespace. This change improves build performance, enables single file deployment, and enables these types to participate in [Hot Reload](xref:test/hot-reload). For more information about this change, see [the related announcement issue](https://github.com/aspnet/Announcements/issues/459) on GitHub. ## ASP.NET Core performance and API improvements Many changes were made to reduce allocations and improve performance across the stack: * Non-allocating [app.Use](xref:Microsoft.AspNetCore.Builder.IApplicationBuilder.Use%2A) extension method. The new overload of `app.Use` requires passing the context to `next` which saves two internal per-request allocations that are required when using the other overload. * Reduced memory allocations when accessing . For more information, see [this GitHub issue](https://github.com/dotnet/aspnetcore/issues/10030). * Use [LoggerMessage.Define](xref:Microsoft.Extensions.Logging.LoggerMessage.Define%2A) for the windows only [HTTP.sys web server](xref:fundamentals/servers/httpsys). The extension methods calls have been replaced with calls to `LoggerMessage.Define`. * Reduce the per connection overhead in [SocketConnection](https://github.com/dotnet/aspnetcore/blob/main/src/Servers/Kestrel/Transport.Sockets/src/Internal/SocketConnection.cs) by ~30%. For more information, see [this GitHub pull request](https://github.com/dotnet/aspnetcore/pull/31308). * Reduce allocations by removing logging delegates in generic types. For more information, see [this GitHub pull request](https://github.com/dotnet/aspnetcore/issues/31340). * Faster GET access (about 50%) to commonly-used features such as , , , , and . For more information, see [this GitHub pull request](https://github.com/dotnet/aspnetcore/pull/31322). * Use single instance strings for known header names, even if they aren't in the preserved header block. Using single instance string helps prevent multiple duplicates of the same string in long lived connections, for example, in . For more information, see [this GitHub issue](https://github.com/dotnet/aspnetcore/issues/31305). * Reuse [HttpProtocol CancellationTokenSource](https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs#L401-L409) in Kestrel. Use the new [CancellationTokenSource.TryReset](xref:System.Threading.CancellationTokenSource.TryReset%2A) method on `CancellationTokenSource` to reuse tokens if they haven’t been canceled. For more information, see [this GitHub issue](https://github.com/dotnet/runtime/issues/48492) and this [video](https://www.youtube.com/watch?v=vNPybpatlUU&t=1h38m28s). * Implement and use an [AdaptiveCapacityDictionary](https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Http/Http/src/Internal/RequestCookieCollection.cs#L24) in [RequestCookieCollection](https://github.com/dotnet/aspnetcore/blob/main/src/Http/Http/src/Internal/RequestCookieCollection.cs) for more efficient access to dictionaries. For more information, see [this GitHub pull request](https://github.com/dotnet/aspnetcore/pull/31360). ### Reduced memory footprint for idle TLS connections For long running TLS connections where data is only occasionally sent back and forth, we’ve significantly reduced the memory footprint of ASP.NET Core apps in .NET 6. This should help improve the scalability of scenarios such as WebSocket servers. This was possible due to numerous improvements in , , and Kestrel. The following sections detail some of the improvements that have contributed to the reduced memory footprint: #### Reduce the size of `System.IO.Pipelines.Pipe` For every connection that is established, two pipes are allocated in Kestrel: * The transport layer to the app for the request. * The application layer to the transport for the response. By shrinking the size of from 368 bytes to 264 bytes (about a 28.2% reduction), 208 bytes per connection are saved (104 bytes per Pipe). #### Pool SocketSender `SocketSender` objects (that subclass ) are around 350 bytes at runtime. Instead of allocating a new `SocketSender` object per connection, they can be pooled. `SocketSender` objects can be pooled because sends are usually very fast. Pooling reduces the per connection overhead. Instead of allocating 350 bytes per connection, only pay 350 bytes per `IOQueue` are allocated. Allocation is done per queue to avoid contention. Our WebSocket server with 5000 idle connections went from allocating ~1.75 MB (350 bytes * 5000) to allocating ~2.8 kb (350 bytes * 8) for `SocketSender` objects. #### Zero bytes reads with SslStream Bufferless reads are a technique employed in ASP.NET Core to avoid renting memory from the memory pool if there’s no data available on the socket. Prior to this change, our WebSocket server with 5000 idle connections required ~200 MB without TLS compared to ~800 MB with TLS. Some of these allocations (4k per connection) were from Kestrel having to hold on to an buffer while waiting for the reads on to complete. Given that these connections were idle, none of reads completed and returned their buffers to the `ArrayPool`, forcing the `ArrayPool` to allocate more memory. The remaining allocations were in `SslStream` itself: 4k buffer for TLS handshakes and 32k buffer for normal reads. In .NET 6, when the user performs a zero byte read on `SslStream` and it has no data available, `SslStream` internally performs a zero-byte read on the underlying wrapped stream. In the best case (idle connection), these changes result in a savings of 40 Kb per connection while still allowing the consumer (Kestrel) to be notified when data is available without holding on to any unused buffers. #### Zero byte reads with PipeReader With bufferless reads supported on `SslStream`, an option was added to perform zero byte reads to `StreamPipeReader`, the internal type that adapts a `Stream` into a `PipeReader`. In Kestrel, a`StreamPipeReader` is used to adapt the underlying `SslStream` into a `PipeReader`. Therefore it was necessary to expose these zero byte read semantics on the `PipeReader`. A `PipeReader` can now be created that supports zero bytes reads over any underlying `Stream` that supports zero byte read semantics (e.g,. `SslStream`, , etc) using the following API: ```dotnetcli var reader = PipeReader.Create(stream, new StreamPipeReaderOptions(useZeroByteReads: true)); ``` #### Remove slabs from the `SlabMemoryPool` To reduce fragmentation of the heap, Kestrel employed a technique where it allocated slabs of memory of 128 KB as part of its memory pool. The slabs were then further divided into 4 KB blocks that were used by Kestrel internally. The slabs had to be larger than 85 KB to force allocation on the large object heap to try and prevent the GC from relocating this array. However, with the introduction of the new GC generation, [Pinned Object Heap](https://devblogs.microsoft.com/dotnet/internals-of-the-poh/) (POH), it no longer makes sense to allocate blocks on slab. Kestrel now directly allocates blocks on the POH, reducing the complexity involved in managing the memory pool. This change should make easier to perform future improvements such as making it easier to shrink the memory pool used by Kestrel. ### IAsyncDisposable supported is now available for controllers, Razor Pages, and View Components. Asynchronous versions have been added to the relevant interfaces in factories and activators: * The new methods offer a default interface implementation that delegates to the synchronous version and calls . * The implementations override the default implementation and handle disposing `IAsyncDisposable` implementations. * The implementations favor `IAsyncDisposable` over `IDisposable` when both interfaces are implemented. * Extenders must override the new methods included to support `IAsyncDisposable` instances. `IAsyncDisposable` is beneficial when working with: * Asynchronous enumerators, for example, in asynchronous streams. * Unmanaged resources that have resource-intensive I/O operations to release. When implementing this interface, use the `DisposeAsync` method to release resources. Consider a controller that creates and uses a . `Utf8JsonWriter` is an `IAsyncDisposable` resource: [!code-csharp[](aspnetcore-6.0/samples/HomeController.cs?name=snippet&highlight=1,9)] `IAsyncDisposable` must implement `DisposeAsync`: [!code-csharp[](aspnetcore-6.0/samples/HomeController.cs?name=snippet2)] ### Vcpkg port for SignalR C++ client [Vcpkg](https://github.com/microsoft/vcpkg) is a cross-platform command-line package manager for C and C++ libraries. We’ve recently added a port to `vcpkg` to add `CMake` native support for the SignalR C++ client. `vcpkg` also works with MSBuild. The SignalR client can be added to a CMake project with the following snippet when the vcpkg is included in the toolchain file: ```dotnetcli find_package(microsoft-signalr CONFIG REQUIRED) link_libraries(microsoft-signalr::microsoft-signalr) ``` With the preceding snippet, the SignalR C++ client is ready to use [`#include`](https://github.com/halter73/SignalR-Client-Cpp-Sample/blob/main/sample.cpp#L3-L5) and used in a project without any additional configuration. For a complete example of a C++ application that utilizes the SignalR C++ client, see the [halter73/SignalR-Client-Cpp-Sample](https://github.com/halter73/SignalR-Client-Cpp-Sample) repository. ## Blazor ### Project template changes Several project template changes were made for Blazor apps, including the use of the `Pages/_Layout.cshtml` file for layout content that appeared in the `_Host.cshtml` file for earlier Blazor Server apps. Study the changes by creating an app from a 6.0 project template or accessing the ASP.NET Core reference source for the project templates: * [Blazor Server](https://github.com/dotnet/aspnetcore/tree/v6.0.0/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp) * [Blazor WebAssembly](https://github.com/dotnet/aspnetcore/tree/v6.0.0/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp) ### Blazor WebAssembly native dependencies support Blazor WebAssembly apps can use native dependencies built to run on WebAssembly. For more information, see . ### WebAssembly Ahead-of-time (AOT) compilation and runtime relinking Blazor WebAssembly supports ahead-of-time (AOT) compilation, where you can compile your .NET code directly into WebAssembly. AOT compilation results in runtime performance improvements at the expense of a larger app size. Relinking the .NET WebAssembly runtime trims unused runtime code and thus improves download speed. For more information, see [Ahead-of-time (AOT) compilation](xref:blazor/host-and-deploy/webassembly?view=aspnetcore-6.0#ahead-of-time-aot-compilation) and [Runtime relinking](xref:blazor/tooling/webassembly?view=aspnetcore-6.0#runtime-relinking). ### Persist prerendered state Blazor supports persisting state in a prerendered page so that the state doesn't need to be recreated when the app is fully loaded. For more information, see . ### Error boundaries Error boundaries provide a convenient approach for handling exceptions on the UI level. For more information, see . ### SVG support The [`` element](https://developer.mozilla.org/docs/Web/SVG/Element/foreignObject) element is supported to display arbitrary HTML within an SVG. For more information, see . ### Blazor Server support for byte array transfer in JS Interop Blazor supports optimized byte array JS interop that avoids encoding and decoding byte arrays into Base64. For more information, see the following resources: * * ### Query string enhancements Support for working with query strings is improved. For more information, see . ### Binding to select multiple Binding supports multiple option selection with `` elements. For more information, see the following resources: * * ### Head (``) content control Razor components can modify the HTML `` element content of a page, including setting the page's title (`` element) and modifying metadata (`<meta>` elements). For more information, see [Control `<head>` content in ASP.NET Core Blazor apps](xref:blazor/components/control-head-content?view=aspnetcore-6.0). ### Generate Angular and React components Generate framework-specific JavaScript components from Razor components for web frameworks, such as Angular or React. For more information, see <xref:blazor/components/index?view=aspnetcore-6.0#generate-angular-and-react-components>. ### Render components from JavaScript Render Razor components dynamically from JavaScript for existing JavaScript apps. For more information, see <xref:blazor/components/index?view=aspnetcore-6.0#render-razor-components-from-javascript>. ### Custom elements Experimental support is available for building custom elements, which use standard HTML interfaces. For more information, see <xref:blazor/components/index?view=aspnetcore-6.0#blazor-custom-elements>. ### Infer component generic types from ancestor components An ancestor component can cascade a type parameter by name to descendants using the new `[CascadingTypeParameter]` attribute. For more information, see <xref:blazor/components/index?view=aspnetcore-6.0#cascaded-generic-type-support>. ### Dynamically rendered components Use the new built-in `DynamicComponent` component to render components by type. For more information, see <xref:blazor/components/dynamiccomponent?view=aspnetcore-6.0>. ### Improved Blazor accessibility Use the new `FocusOnNavigate` component to set the UI focus to an element based on a CSS selector after navigating from one page to another. For more information, see <xref:blazor/fundamentals/routing?view=aspnetcore-6.0#focus-an-element-on-navigation>. ### Custom event argument support Blazor supports custom event arguments, which enable you to pass arbitrary data to .NET event handlers with custom events. For more information, see <xref:blazor/components/event-handling?view=aspnetcore-6.0#custom-event-arguments>. ### Required parameters Apply the new `[EditorRequired]` attribute to specify a required component parameter. For more information, see <xref:blazor/components/index?view=aspnetcore-6.0#component-parameters>. ### Collocation of JavaScript files with pages, views, and components Collocate JavaScript files for pages, views, and Razor components as a convenient way to organize scripts in an app. For more information, see <xref:blazor/js-interop/index?view=aspnetcore-6.0#load-a-script-from-an-external-javascript-file-js-collocated-with-a-component>. ### JavaScript initializers JavaScript initializers execute logic before and after a Blazor app loads. For more information, see <xref:blazor/js-interop/index?view=aspnetcore-6.0#javascript-initializers>. ### Streaming JavaScript interop Blazor now supports streaming data directly between .NET and JavaScript. For more information, see the following resources: * [Stream from .NET to JavaScript](xref:blazor/js-interop/call-javascript-from-dotnet?view=aspnetcore-6.0#stream-from-net-to-javascript) * [Stream from JavaScript to .NET](xref:blazor/js-interop/call-dotnet-from-javascript?view=aspnetcore-6.0#stream-from-javascript-to-net) ### Generic type constraints Generic type parameters are now supported. For more information, see <xref:blazor/components/index?view=aspnetcore-6.0#generic-type-parameter-support>. ### WebAssembly deployment layout Use a deployment layout to enable Blazor WebAssembly app downloads in restricted security environments. For more information, see <xref:blazor/host-and-deploy/webassembly-deployment-layout?view=aspnetcore-6.0>. ### New Blazor articles In addition to the Blazor features described in the preceding sections, new Blazor articles are available on the following subjects: * <xref:blazor/file-downloads>: Learn how to download a file using native `byte[]` streaming interop to ensure efficient transfer to the client. * <xref:blazor/images-and-documents>: Discover how to work with images and documents in Blazor apps, including how to stream image and document data. ## Build Blazor Hybrid apps with .NET MAUI, WPF, and Windows Forms Use Blazor Hybrid to blend desktop and mobile native client frameworks with .NET and Blazor: * .NET Multi-platform App UI (.NET MAUI) is a cross-platform framework for creating native mobile and desktop apps with C# and XAML. * Blazor Hybrid apps can be built with Windows Presentation Foundation (WPF) and Windows Forms frameworks. > [!IMPORTANT] > Blazor Hybrid is in preview and shouldn't be used in production apps until final release. For more information, see the following resources: * [Preview ASP.NET Core Blazor Hybrid documentation](xref:blazor/hybrid/index) * [What is .NET MAUI?](/dotnet/maui/what-is-maui) * [Microsoft .NET Blog (category: ".NET MAUI")](https://devblogs.microsoft.com/dotnet/category/maui/) ## Kestrel [HTTP/3](https://datatracker.ietf.org/doc/html/draft-ietf-quic-http-34) is currently in draft and therefore subject to change. HTTP/3 support in ASP.NET Core is not released, it's a preview feature included in .NET 6. Kestrel now supports HTTP/3. For more information, see <xref:fundamentals/servers/kestrel/http3> and the blog entry [HTTP/3 support in .NET 6](https://devblogs.microsoft.com/dotnet/http-3-support-in-dotnet-6/). ### New Kestrel logging categories for selected logging Prior to this change, enabling verbose logging for Kestrel was prohibitively expensive as all of Kestrel shared the `Microsoft.AspNetCore.Server.Kestrel` logging category name. `Microsoft.AspNetCore.Server.Kestrel` is still available, but the following new subcategories allow for more control of logging: * `Microsoft.AspNetCore.Server.Kestrel` (current category): `ApplicationError`, `ConnectionHeadResponseBodyWrite`, `ApplicationNeverCompleted`, `RequestBodyStart`, `RequestBodyDone`, `RequestBodyNotEntirelyRead`, `RequestBodyDrainTimedOut`, `ResponseMinimumDataRateNotSatisfied`, `InvalidResponseHeaderRemoved`, `HeartbeatSlow`. * `Microsoft.AspNetCore.Server.Kestrel.BadRequests`: `ConnectionBadRequest`, `RequestProcessingError`, `RequestBodyMinimumDataRateNotSatisfied`. * `Microsoft.AspNetCore.Server.Kestrel.Connections`: `ConnectionAccepted`, `ConnectionStart`, `ConnectionStop`, `ConnectionPause`, `ConnectionResume`, `ConnectionKeepAlive`, `ConnectionRejected`, `ConnectionDisconnect`, `NotAllConnectionsClosedGracefully`, `NotAllConnectionsAborted`, `ApplicationAbortedConnection`. * `Microsoft.AspNetCore.Server.Kestrel.Http2`: `Http2ConnectionError`, `Http2ConnectionClosing`, `Http2ConnectionClosed`, `Http2StreamError`, `Http2StreamResetAbort`, `HPackDecodingError`, `HPackEncodingError`, `Http2FrameReceived`, `Http2FrameSending`, `Http2MaxConcurrentStreamsReached`. * `Microsoft.AspNetCore.Server.Kestrel.Http3`: `Http3ConnectionError`, `Http3ConnectionClosing`, `Http3ConnectionClosed`, `Http3StreamAbort`, `Http3FrameReceived`, `Http3FrameSending`. Existing rules continue to work, but you can now be more selective on which rules you enable. For example, the observability overhead of enabling `Debug` logging for just bad requests is greatly reduced and can be enabled with the following configuration: [!code-xml[](aspnetcore-6.0/samples/WebApp1/appsettings.Test.json?highlight=6)] Log filtering applies rules with the longest matching category prefix. For more information, see [How filtering rules are applied](xref:fundamentals/logging/index?view=aspnetcore-6.0#how-filtering-rules-are-applied) ### Emit KestrelServerOptions via EventSource event The [KestrelEventSource](https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Servers/Kestrel/Core/src/Internal/Infrastructure/KestrelEventSource.cs) emits a new event containing the JSON-serialized <xref:Microsoft.AspNetCore.Server.Kestrel.KestrelServerOptions> when enabled with verbosity `EventLevel.LogAlways`. This event makes it easier to reason about the server behavior when analyzing collected traces. The following JSON is an example of the event payload: ```json { "AllowSynchronousIO": false, "AddServerHeader": true, "AllowAlternateSchemes": false, "AllowResponseHeaderCompression": true, "EnableAltSvc": false, "IsDevCertLoaded": true, "RequestHeaderEncodingSelector": "default", "ResponseHeaderEncodingSelector": "default", "Limits": { "KeepAliveTimeout": "00:02:10", "MaxConcurrentConnections": null, "MaxConcurrentUpgradedConnections": null, "MaxRequestBodySize": 30000000, "MaxRequestBufferSize": 1048576, "MaxRequestHeaderCount": 100, "MaxRequestHeadersTotalSize": 32768, "MaxRequestLineSize": 8192, "MaxResponseBufferSize": 65536, "MinRequestBodyDataRate": "Bytes per second: 240, Grace Period: 00:00:05", "MinResponseDataRate": "Bytes per second: 240, Grace Period: 00:00:05", "RequestHeadersTimeout": "00:00:30", "Http2": { "MaxStreamsPerConnection": 100, "HeaderTableSize": 4096, "MaxFrameSize": 16384, "MaxRequestHeaderFieldSize": 16384, "InitialConnectionWindowSize": 131072, "InitialStreamWindowSize": 98304, "KeepAlivePingDelay": "10675199.02:48:05.4775807", "KeepAlivePingTimeout": "00:00:20" }, "Http3": { "HeaderTableSize": 0, "MaxRequestHeaderFieldSize": 16384 } }, "ListenOptions": [ { "Address": "https://127.0.0.1:7030", "IsTls": true, "Protocols": "Http1AndHttp2" }, { "Address": "https://[::1]:7030", "IsTls": true, "Protocols": "Http1AndHttp2" }, { "Address": "http://127.0.0.1:5030", "IsTls": false, "Protocols": "Http1AndHttp2" }, { "Address": "http://[::1]:5030", "IsTls": false, "Protocols": "Http1AndHttp2" } ] } ``` ### New DiagnosticSource event for rejected HTTP requests Kestrel now emits a new `DiagnosticSource` event for HTTP requests rejected at the server layer. Prior to this change, there was no way to observe these rejected requests. The new `DiagnosticSource` event `Microsoft.AspNetCore.Server.Kestrel.BadRequest` contains a <xref:Microsoft.AspNetCore.Http.Features.IBadRequestExceptionFeature> that can be used to introspect the reason for rejecting the request. [!code-csharp[](aspnetcore-6.0/samples/WebApp1/Program.cs?name=snippet_diag)] For more information, see <xref:fundamentals/servers/kestrel/diagnostics>. ### Create a ConnectionContext from an Accept Socket The new <xref:Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionContextFactory> makes it possible to create a <xref:Microsoft.AspNetCore.Connections.ConnectionContext> from an accepted socket. This makes it possible to build a custom socket-based <xref:Microsoft.AspNetCore.Connections.IConnectionListenerFactory> without losing out on all the performance work and pooling happening in [SocketConnection](https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Servers/Kestrel/Transport.Sockets/src/Internal/SocketConnection.cs). See [this example of a custom IConnectionListenerFactory](https://github.com/davidfowl/TcpProxy/blob/main/Backend/DelegatedConnectionListenerFactory.cs) which shows how to use this `SocketConnectionContextFactory`. ### Kestrel is the default launch profile for Visual Studio The default launch profile for all new dotnet web projects is Kestrel. Starting Kestrel is significantly faster and results in a more responsive experience while developing apps. IIS Express is still available as a launch profile for scenarios such as Windows Authentication or port sharing. ### Localhost ports for Kestrel are random See [Template generated ports for Kestrel](#tgp) in this document for more information. ## Authentication and authorization ### Authentication servers .NET 3 to .NET 5 used [IdentityServer4](https://identityserver4.readthedocs.io) as part of our template to support the issuing of JWT tokens for SPA and Blazor applications. The templates now use the [Duende Identity Server](https://docs.duendesoftware.com). If you are extending the identity models and are updating existing projects, update the namespaces in your code from `IdentityServer4.IdentityServer` to `Duende.IdentityServer` and follow their migration instructions. The license model for Duende Identity Server has changed to a reciprocal license, which may require license fees when it's used commercially in production. See the [Duende license page](https://duendesoftware.com/products/identityserver#pricing) for more details. ### Delayed client certificate negotiation Developers can now opt-in to using delayed client certificate negotiation by specifying [ClientCertificateMode.DelayCertificate](xref:Microsoft.AspNetCore.Server.Kestrel.Https.ClientCertificateMode.DelayCertificate) on the <xref:Microsoft.AspNetCore.Server.Kestrel.Https.HttpsConnectionAdapterOptions>. This only works with HTTP/1.1 connections because HTTP/2 forbids delayed certificate renegotiation. The caller of this API must buffer the request body before requesting the client certificate: [!code-csharp[](aspnetcore-6.0/samples/WebApp1/Program.cs?name=snippert_dcrt)] ### `OnCheckSlidingExpiration` event for controlling cookie renewal Cookie authentication sliding expiration can now be customized or suppressed using the new <xref:Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationEvents.OnCheckSlidingExpiration>. For example, this event can be used by a single-page app that needs to periodically ping the server without affecting the authentication session. ## Miscellaneous ### Hot Reload Quickly make UI and code updates to running apps without losing app state for faster and more productive developer experience using [Hot Reload](xref:test/hot-reload). For more information, see <xref:test/hot-reload> and [Update on .NET Hot Reload progress and Visual Studio 2022 Highlights](https://devblogs.microsoft.com/dotnet/update-on-net-hot-reload-progress-and-visual-studio-2022-highlights/). <!-- Notes: ### Single-file publishing Moved to .NET 7 https://github.com/dotnet/aspnetcore/issues/27888#event-5487147790 --> ### Improved single-page app (SPA) templates The ASP.NET Core project templates have been updated for Angular and React to use an improved pattern for single-page apps that is more flexible and more closely aligns with common patterns for modern front-end web development. Previously, the ASP.NET Core template for Angular and React used specialized middleware during development to launch the development server for the front-end framework and then proxy requests from ASP.NET Core to the development server. The logic for launching the front-end development server was specific to the command-line interface for the corresponding front-end framework. Supporting additional front-end frameworks using this pattern meant adding additional logic to ASP.NET Core. The updated ASP.NET Core templates for Angular and React in .NET 6 flips this arrangement around and take advantage of the built-in proxying support in the development servers of most modern front-end frameworks. When the ASP.NET Core app is launched, the front-end development server is launched just as before, but the development server is configured to proxy requests to the backend ASP.NET Core process. All of the front-end specific configuration to setup proxying is part of the app, not ASP.NET Core. Setting up ASP.NET Core projects to work with other front-end frameworks is now straight-forward: setup the front-end development server for the chosen framework to proxy to the ASP.NET Core backend using the pattern established in the Angular and React templates. The startup code for the ASP.NET Core app no longer needs any single-page app-specific logic. The logic for starting the front-end development server during development is injecting into the app at runtime by the new [Microsoft.AspNetCore.SpaProxy](https://www.nuget.org/packages/microsoft.aspnetcore.spaproxy) package. Fallback routing is handled using endpoint routing instead of SPA-specific middleware. Templates that follow this pattern can still be run as a single project in Visual Studio or using `dotnet run` from the command-line. When the app is published, the front-end code in the *ClientApp* folder is built and collected as before into the web root of the host ASP.NET Core app and served as static files. Scripts included in the template configure the front-end development server to use HTTPS using the ASP.NET Core development certificate. ### Draft HTTP/3 support in .NET 6 [HTTP/3](https://datatracker.ietf.org/doc/html/draft-ietf-quic-http-34) is currently in draft and therefore subject to change. HTTP/3 support in ASP.NET Core is not released, it's a preview feature included in .NET 6. See the blog entry [HTTP/3 support in .NET 6](https://devblogs.microsoft.com/dotnet/http-3-support-in-dotnet-6/). ### Nullable Reference Type Annotations Portions of the [ASP.NET Core 6.0 source code](https://github.com/dotnet/aspnetcore/tree/v6.0.0/src) has had [nullability annotations](/dotnet/csharp/nullable-migration-strategies) applied. By utilizing the new [Nullable feature in C# 8](/dotnet/csharp/whats-new/csharp-8#nullable-reference-types), ASP.NET Core can provide additional compile-time safety in the handling of reference types. For example, protecting against `null` reference exceptions. Projects that have opted in to using nullable annotations may see new build-time warnings from ASP.NET Core APIs. To enable nullable reference types, add the following property to project files: ```xml <PropertyGroup> <Nullable>enable</Nullable> </PropertyGroup> ``` For more information, see [Nullable reference types](/dotnet/csharp/nullable-references). <!-- REVIEW This is probably not worth adding #### SignalR – Nullable annotations The [ASP.NET Core SignalR Client package](https://www.nuget.org/packages/Microsoft.AspNetCore.SignalR.Client/) has been annotated for nullability. --> ### Source Code Analysis Several .NET compiler platform analyzers were added that inspect application code for problems such as incorrect middleware configuration or order, routing conflicts, etc. For more information, see <xref:diagnostics/code-analysis>. ### Web app template improvements The web app templates: * Use the new [minimal hosting model](xref:migration/50-to-60#new-hosting-model). * Significantly reduces the number of files and lines of code required to create an app. For example, the ASP.NET Core empty web app creates one C# file with four lines of code and is a complete app. * Unifies `Startup.cs` and `Program.cs` into a single `Program.cs` file. * Uses [top-level statements](/dotnet/csharp/fundamentals/program-structure/top-level-statements) to minimize the code required for an app. * Uses [global `using` directives](/dotnet/csharp/whats-new/csharp-10#global-using-directives) to eliminate or minimize the number of [`using` statement](/dotnet/csharp/language-reference/keywords/using-statement) lines required. <a name="tgp"></a> ### Template generated ports for Kestrel Random ports are assigned during project creation for use by the Kestrel web server. Random ports help minimize a port conflict when multiple projects are run on the same machine. When a project is created, a random HTTP port between 5000-5300 and a random HTTPS port between 7000-7300 is specified in the generated `Properties/launchSettings.json` file. The ports can be changed in the `Properties/launchSettings.json` file. If no port is specified, Kestrel defaults to the HTTP 5000 and HTTPS 5001 ports. For more information, see <xref:fundamentals/servers/kestrel/endpoints>. ### New logging defaults The following changes were made to both `appsettings.json` and `appsettings.Development.json`: ```diff - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" + "Microsoft.AspNetCore": "Warning" ``` The change from `"Microsoft": "Warning"` to `"Microsoft.AspNetCore": "Warning"` results in logging all informational messages from the `Microsoft` namespace ***except*** `Microsoft.AspNetCore`. For example, `Microsoft.EntityFrameworkCore` is now logged at the informational level. <!-- TODO add and routing --> ### Developer exception page Middleware added automatically In the [development environment](xref:fundamentals/environments), the <xref:Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware> is added by default. It's no longer necessary to add the following code to web UI apps: ```csharp if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } ``` ### Support for Latin1 encoded request headers in HttpSysServer `HttpSysServer` now supports decoding request headers that are `Latin1` encoded by setting the <xref:Microsoft.AspNetCore.Server.HttpSys.HttpSysOptions.UseLatin1RequestHeaders> property on <xref:Microsoft.AspNetCore.Server.HttpSys.HttpSysOptions> to `true`: [!code-csharp[](aspnetcore-6.0/samples/WebApp1/Program.cs?name=snippet_latin)] ### The ASP.NET Core Module logs include timestamps and PID The <xref:host-and-deploy/aspnet-core-module> (ANCM) enhanced diagnostic logs include timestamps and [PID](https://wikipedia.org/wiki/Process_identifier) of the process emitting the logs. Logging timestamps and PID makes it easier to diagnose issues with overlapping process restarts in IIS when multiple IIS worker processes are running. The resulting logs now resemble the sample output show below: ```dotnetcli [2021-07-28T19:23:44.076Z, PID: 11020] [aspnetcorev2.dll] Initializing logs for 'C:\<path>\aspnetcorev2.dll'. Process Id: 11020. File Version: 16.0.21209.0. Description: IIS ASP.NET Core Module V2. Commit: 96475a2acdf50d7599ba8e96583fa73efbe27912. [2021-07-28T19:23:44.079Z, PID: 11020] [aspnetcorev2.dll] Resolving hostfxr parameters for application: '.\InProcessWebSite.exe' arguments: '' path: 'C:\Temp\e86ac4e9ced24bb6bacf1a9415e70753\' [2021-07-28T19:23:44.080Z, PID: 11020] [aspnetcorev2.dll] Known dotnet.exe location: '' ``` ### Configurable unconsumed incoming buffer size for IIS The IIS server previously only buffered 64 KiB of unconsumed request bodies. The 64 KiB buffering resulted in reads being constrained to that maximum size, which impacts the performance with large incoming bodies such as uploads. In .NET 6 , the default buffer size changes from 64 KiB to 1 MiB which should improve throughput for large uploads. In our tests, a 700 MiB upload that used to take 9 seconds now only takes 2.5 seconds. The downside of a larger buffer size is an increased per-request memory consumption when the app isn’t quickly reading from the request body. So, in addition to changing the default buffer size, the buffer size configurable, allowing apps to configure the buffer size based on workload. ### View Components Tag Helpers Consider a view component with an optional parameter, as shown in the following code: ```csharp class MyViewComponent { IViewComponentResult Invoke(bool showSomething = false) { ... } } ``` With ASP.NET Core 6, the tag helper can be invoked without having to specify a value for the `showSomething` parameter: ```razor <vc:my /> ``` ### Angular template updated to Angular 12 The ASP.NET Core 6.0 template for Angular now uses Angular 12. The React template has been updated to [React 17](https://reactjs.org/blog/2020/10/20/react-v17.html). ### Configurable buffer threshold before writing to disk in Json.NET output formatter **Note**: We recommend using the <xref:System.Text.Json?displayProperty=fullName> output formatter except when the `Newtonsoft.Json` serializer is required for compatibility reasons. The `System.Text.Json` serializer is fully `async` and works efficiently for larger payloads. The `Newtonsoft.Json` output formatter by default buffers responses up to 32 KiB in memory before buffering to disk. This is to avoid performing synchronous IO, which can result in other side-effects such as thread starvation and application deadlocks. However, if the response is larger than 32 KiB, considerable disk I/O occurs. The memory threshold is now configurable via the [MvcNewtonsoftJsonOptions.OutputFormatterMemoryBufferThreshold](xref:Microsoft.AspNetCore.Mvc.MvcNewtonsoftJsonOptions.OutputFormatterMemoryBufferThreshold) property before buffering to disk: [!code-csharp[](aspnetcore-6.0/samples/WebApp1/Program.cs?name=snippet_jsonb)] For more information, see [this GitHub pull request](https://github.com/dotnet/aspnetcore/pull/32747) and the [NewtonsoftJsonOutputFormatterTest.cs](https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Mvc/Mvc.NewtonsoftJson/test/NewtonsoftJsonOutputFormatterTest.cs) file. ### Faster get and set for HTTP headers New APIs were added to expose all common headers available on <!--REVIEW: System.Net.Http.HeaderNames changed to --> <xref:Microsoft.Net.Http.Headers.HeaderNames?displayProperty=fullName> as properties on the <xref:Microsoft.AspNetCore.Http.IHeaderDictionary> resulting in an easier to use API. For example, the in-line middleware in the following code gets and sets both request and response headers using the new APIs: [!code-csharp[](aspnetcore-6.0/samples/WebApp1/Program.cs?name=snippet_hdrs)] For implemented headers the get and set accessors are implemented by going directly to the field and bypassing the lookup. For non-implemented headers, the accessors can bypass the initial lookup against implemented headers and directly perform the `Dictionary<string, StringValues>` lookup. Avoiding the lookup results in faster access for both scenarios. ### Async streaming <!-- TODO Review from: https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-net-6-preview-4/#async-streaming - Blog writes ASP.NET Core now supports async streaming from controller actions all the way down to the response JSON formatter. What does "all the way down to the" mean? That won't machine translate. What else is new in async streaming beside controller actions and responses? --> ASP.NET Core now supports asynchronous streaming from controller actions and responses from the JSON formatter. Returning an `IAsyncEnumerable` from an action no longer buffers the response content in memory before it gets sent. Not buffering helps reduce memory usage when returning large datasets that can be asynchronously enumerated. Note that Entity Framework Core provides implementations of `IAsyncEnumerable` for querying the database. The improved support for `IAsyncEnumerable` in ASP.NET Core in .NET 6 can make using EF Core with ASP.NET Core more efficient. For example, the following code no longer buffers the product data into memory before sending the response: [!code-csharp[](aspnetcore-6.0/samples/WebMvcEF/Controllers/MoviesController.cs?name=snippet1)] However, when using lazy loading in EF Core, this new behavior may result in errors due to concurrent query execution while the data is being enumerated. Apps can revert back to the previous behavior by buffering the data: [!code-csharp[](aspnetcore-6.0/samples/WebMvcEF/Controllers/MoviesController.cs?name=snippet2)] See the related [announcement](https://github.com/aspnet/Announcements/issues/463) for additional details about this change in behavior. ### HTTP logging middleware HTTP logging is a new built-in middleware that logs information about HTTP requests and HTTP responses including the headers and entire body: [!code-csharp[](aspnetcore-6.0/samples/WebApp1/Program.cs?name=snippet_httplg&highlight=4)] Navigating to `/` with the previous code logs information similar to the following output: ```dotnetcli info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1] Request: Protocol: HTTP/2 Method: GET Scheme: https PathBase: Path: / Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9 Cache-Control: max-age=0 Connection: close Cookie: [Redacted] Host: localhost:44372 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30 sec-ch-ua: [Redacted] sec-ch-ua-mobile: [Redacted] sec-ch-ua-platform: [Redacted] upgrade-insecure-requests: [Redacted] sec-fetch-site: [Redacted] sec-fetch-mode: [Redacted] sec-fetch-user: [Redacted] sec-fetch-dest: [Redacted] info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2] Response: StatusCode: 200 Content-Type: text/plain; charset=utf-8 ``` The preceding output was enabled with the following `appsettings.Development.json` file: [!code-json[](aspnetcore-6.0/samples/WebApp1/appsettings.development.json?highlight=6)] HTTP logging provides logs of: * HTTP Request information * Common properties * Headers * Body * HTTP Response information To configure the HTTP logging middleware, specify <xref:Microsoft.AspNetCore.HttpLogging.HttpLoggingOptions>: [!code-csharp[](aspnetcore-6.0/samples/WebApp1/Program.cs?name=snippet_httplg2&highlight=1,4-13)] ### IConnectionSocketFeature The <xref:Microsoft.AspNetCore.Connections.Features.IConnectionSocketFeature> request feature provides access to the underlying accept socket associated with the current request. It can be accessed via the <xref:Microsoft.AspNetCore.Http.Features.FeatureCollection> on `HttpContext`. For example, the following app sets the <xref:System.Net.Sockets.Socket.LingerState> property on the accepted socket: [!code-csharp[](aspnetcore-6.0/samples/WebApp1/Program.cs?name=snippet_icsf)] ### Generic type constraints in Razor When defining generic type parameters in Razor using the `@typeparam` directive, generic type constraints can now be specified using the standard C# syntax: ### Smaller SignalR, Blazor Server, and MessagePack scripts The SignalR, MessagePack, and Blazor Server scripts are now significantly smaller, enabling smaller downloads, less JavaScript parsing and compiling by the browser, and faster start-up. The size reductions: * `signalr.js`: 70% * `blazor.server.js`: 45% The smaller scripts are a result of a community contribution from [Ben Adams](https://twitter.com/ben_a_adams). For more information on the details of the size reduction, see [Ben's GitHub pull request](https://github.com/dotnet/aspnetcore/pull/30320). ### Enable Redis profiling sessions A community contribution from [Gabriel Lucaci](https://twitter.com/_glucaci) enables Redis profiling session with [Microsoft.Extensions.Caching.StackExchangeRedis](https://www.nuget.org/packages/Microsoft.Extensions.Caching.StackExchangeRedis): [!code-csharp[](aspnetcore-6.0/samples/WebApp1/Program.cs?name=snippet_red)] For more information, see [StackExchange.Redis Profiling](https://stackexchange.github.io/StackExchange.Redis/Profiling_v2.html). ### Shadow copying in IIS An experimental feature has been added to the <xref:host-and-deploy/aspnet-core-module> to add support for [shadow copying application assemblies](/dotnet/framework/app-domains/shadow-copy-assemblies). Currently .NET locks application binaries when running on Windows making it impossible to replace binaries when the app is running. While our recommendation remains to use an [app offline file](xref:host-and-deploy/iis/app-offline), we recognize there are certain scenarios (for example FTP deployments) where it isn’t possible to do so. In such scenarios, enable shadow copying by customizing the ASP.NET Core module handler settings. In most cases, ASP.NET Core apps do not have a `web.config` checked into source control that you can modify. In ASP.NET Core, `web.config` is ordinarily generated by the SDK. The following sample `web.config` can be used to get started: ```xml <?xml version="1.0" encoding="utf-8"?> <configuration> <!-- To customize the asp.net core module uncomment and edit the following section. For more info see https://go.microsoft.com/fwlink/?linkid=838655 --> <system.webServer> <handlers> <remove name="aspNetCore"/> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified"/> </handlers> <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout"> <handlerSettings> <handlerSetting name="experimentalEnableShadowCopy" value="true" /> <handlerSetting name="shadowCopyDirectory" value="../ShadowCopyDirectory/" /> <!-- Only enable handler logging if you encounter issues--> <!--<handlerSetting name="debugFile" value=".\logs\aspnetcore-debug.log" />--> <!--<handlerSetting name="debugLevel" value="FILE,TRACE" />--> </handlerSettings> </aspNetCore> </system.webServer> </configuration> ``` Shadow copying in IIS is an experimental feature that is not guaranteed to be part of ASP.NET Core. Please leave feedback on IIS Shadow copying in [this GitHub issue](https://github.com/dotnet/AspNetCore.Docs/issues/23733). ## Additional resources * <xref:migration/50-to-60-samples> * [What's new in .NET 6](/dotnet/core/whats-new/dotnet-6)