June 17th, 2021

ASP.NET Core updates in .NET 6 Preview 5

Daniel Roth
Principal Product Manager

.NET 6 Preview 5 is now available and includes many great new improvements to ASP.NET Core.

Here’s what’s new in this preview release:

  • .NET Hot Reload updates for dotnet watch
  • ASP.NET Core SPA templates updated to Angular 11 and React 17
  • Use Razor syntax in SVG foreignObject elements
  • Specify null for Action and RenderFragment component parameters
  • Reduced Blazor WebAssembly download size with runtime relinking
  • Configurable buffer threshold before writing to disk in Json.NET output formatter
  • Subcategories for better filtering of Kestrel logs
  • Faster get and set for HTTP headers
  • Configurable unconsumed incoming buffer size for IIS

Get started

To get started with ASP.NET Core in .NET 6 Preview 5, install the .NET 6 SDK.

Note: If you installed .NET 6 Preview 4 previously (either directly or by installing .NET MAUI), then you may run into issues installing and running .NET 6 Preview 5. See the .NET 6 Known Issues for instructions on how to fix up your installation.

If you’re on Windows using Visual Studio, we recommend installing the latest preview of Visual Studio 2019 16.11. Visual Studio 2022 Preview 1 is also releasing today and .NET 6 Preview 5 is included in that release. If you’re on macOS, we recommend installing the latest preview of Visual Studio 2019 for Mac 8.10.

To get setup with .NET MAUI & Blazor for cross-platform native apps, see the latest instructions in the .NET MAUI getting started guide. Be sure to also check out the Announcing .NET MAUI Preview 5 blog post for all the details on what’s new in .NET MAUI in this release.

Note: .NET MAUI is not yet supported in Visual Studio 2022 Preview 1. For .NET MAUI development, please use the latest preview of Visual Studio 2019 16.11 instead.

To install the latest .NET WebAssembly tools for ahead-of-time (AOT) compilation and runtime relinking, run the following command from an elevated command prompt:

dotnet workload install microsoft-net-sdk-blazorwebassembly-aot

If you’ve installed the .NET WebAssembly workload previously, you can update it to .NET 6 Preview 5 by running the following command from an elevated command prompt:

dotnet workload update

Note: There is a known issue with installing optional SDK workloads using the .NET 6 Preview 5 SDK included with Visual Studio 2022 Preview 1. To workaround this issue, install the .NET 6 Preview 5 SDK from https://dot.net/get-dotnet6 after installing Visual Studio 2022 Preview 1.

Upgrade an existing project

To upgrade an existing ASP.NET Core app from .NET 6 Preview 4 to .NET 6 Preview 5:

  • Update all Microsoft.AspNetCore.* package references to 6.0.0-preview.5.*.
  • Update all Microsoft.Extensions.* package references to 6.0.0-preview.5.*.

To upgrade a .NET MAUI Blazor app from .NET 6 Preview 4 to .NET 6 Preview 5 we recommend starting from a new .NET MAUI Blazor project created with the .NET 6 Preview 5 SDK and then copying code over from your original project.

See the full list of breaking changes in ASP.NET Core for .NET 6.

.NET Hot Reload updates for dotnet watch

We’ve been working on various improvements to .NET Hot Reload for .NET 6. Some of these improvements are available in .NET 6 Preview 5, while others are still a work in progress and will be refined in future preview updates.

You no longer need to specify hotReloadProfile in launchSettings.json to use .NET Hot Reload with dotnet watch. .NET Hot Reload with project appropriate behavior is now enabled by default.

When a code edit is made that cannot be hot reloaded (a “rude” edit), dotnet watch will now ask if you want to restart the app to apply the change:

watch : Unable to apply hot reload because of a rude edit. Rebuilding the app...
watch : Unable to handle changes to C:\Users\daroth\Desktop\BlazorApp\Pages\Index.razor.
watch : Do you want to restart your app - Yes (y) / No (n) / Always (a) / Never (v)?

These options have the following behaviors:

  • Choosing Yes will restart the app.
  • Choosing No won’t restart the app and will leave the app running without the changes applied.
  • Choosing Always will restart the app as needed when changes cannot be hot reloaded.
  • Choosing Never won’t restart the app and avoids future prompts.

You can always manually restart the app using Ctrl+R.

Note: There is a known issue in this release that selecting Always still continues to prompt for future rude edits. This will get addressed in a future preview release.

To disable support for .NET Hot Reload when using dotnet watch, use the --no-hot-reload command-line option.

.NET Hot Reload with dotnet watch will also now correctly detect rude edits Blazor WebAssembly apps. Changes applied to Blazor WebAssembly apps will get reapplied to the app when the browser is refreshed or the app is loaded in a separate browser tab or browser instance.

ASP.NET Core SPA templates updated to Angular 11 and React 17

The ASP.NET Core single-page app (SPA) templates for Angular and React have been updated to Angular 11 and React 17. We also expect to further update the Angular template to Angular 12 in a future .NET 6 preview release now that it’s been released.

Support Razor syntax in SVG foreignObject elements

You can now use Razor syntax, including the use of Blazor components, in SVG foreignObject elements:

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
    <rect x="0" y="0" rx="10" ry="10" width="200" height="200" stroke="black" fill="none" />
    <foreignObject x="20" y="20" width="160" height="160">
        <p>@message</p>
    </foreignObject>
</svg>

@code {
    string message = "Wow, it's so nice that this text wraps like it's HTML...because that's what it is!";
}

We also did a bunch of verification and testing to make sure that Blazor has good support for SVG scenarios. We think Blazor’s SVG support is now in good shape. If you hit any issues using SVG in Blazor with this release, please let us know by creating issues on GitHub.

Specify null for Action and RenderFragment component parameters

You can now specify null for the value of Blazor component parameters of type Action and RenderFragment, which simplifies the authoring of components that take optional callback parameters or template parameters.

Reduced Blazor WebAssembly download size with runtime relinking

One of the largest parts of a default Blazor WebAssembly app is the WebAssembly based .NET runtime (dotnet.wasm) that the app carries with it. Blazor WebAssembly already has support for trimming unused code from the .NET core framework libraries. However, the download size of the runtime has been constant.

Not all of the runtime logic is needed by every app. For example, a large part of the runtime logic and related data files are for globalization scenarios. This globalization support enables Blazor WebAssembly apps to handle strings, numbers, dates, etc. based on the current culture. But for apps that don’t need this functionality, all that data and logic is just extra bits.

.NET apps that don’t need globalization functionality can opt out of it and use invariant globalization instead by setting the InvariantGlobalization property to true in their project files. In .NET 5, this would allow a Blazor WebAssembly app to avoid downloading globalization data, but the related logic in the .NET runtime would still be included.

In .NET 6 Preview 5, you can now use the .NET WebAssembly tools (the same tools used for .NET WebAssembly AOT compilation) to relink the runtime to remove unneeded logic and dramatically reduce the size of the runtime. If you have the .NET WebAssembly workload installed, runtime relinking is done automatically when you publish the app. The size reduction is particularly dramatic when using invariant globalization mode.

If you haven’t already, you can install the .NET WebAssembly tools by running the following command from an elevated command prompt:

dotnet workload install microsoft-net-sdk-blazorwebassembly-aot

The following table shows the transfer size of dotnet.wasm for a default Blazor WebAssembly project with .NET 5 and .NET 6:

dotnet.wasm Transfer size (kB)
.NET 5 default 884
.NET 6 default 780
.NET 6 relinked 756
.NET 6 invariant mode 393

Configurable buffer threshold before writing to disk in Json.NET output formatter

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 your response if was larger than 32 KiB this resulted in a lot of avoidable disk I/O. You can now configure the memory threshold before buffering to disk.

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages()
            .AddNewtonsoftJson(options =>
            {
                options.OutputFormatterMemoryBufferThreshold = 48 * 1024;
            });
}

Note: We still recommend using the System.Text.Json output formatter unless you require the Newtonsoft.Json serializer for compatibility reasons. The System.Text.Json serializer is fully async and will work efficiently for any size payload.

Subcategories for better filtering of Kestrel logs

Prior to this change, enabling verbose logging for Kestrel was prohibitively expensive as all of Kestrel shared the same logging category name (Microsoft.AspNetCore.Server.Kestrel). We’ve now split up that category into multiple new subcategories:

  • 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.

While your existing rules will continue to work (log filtering applies rules with the longest matching category prefix), 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 achieved with the following configuration:

{
  "Logging": {
    "LogLevel": {
      "Microsoft.AspNetCore.Kestrel.BadRequests": "Debug"
    }
  }
}

Faster get and set for HTTP headers

We added new API to expose all common headers available on System.Net.Http.HeaderNames as properties on the Microsoft.AspNetCore.Http.IHeaderDictionary resulting in an easier to use API. For example, the in-line middleware below gets/sets both request and response headers using the new APIs:

app.Use(async (context, next) =>
{
    var hostHeader = context.Request.Headers.Host;
    app.Logger.LogInformation("Host header: {host}", hostHeader);
    context.Response.Headers.XPoweredBy = "ASP.NET Core 6.0-preview5";
    await next.Invoke(context);
    var dateHeader = context.Response.Headers.Date;
    app.Logger.LogInformation("Response date: {date}", dateHeader);
});

For implemented headers the get/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. This results in faster access for both scenarios.

Method Branch Type Mean Op/s Delta
GetHeaders preview4 Plaintext 25.793 ns 38,770,569.6
GetHeaders preview5 Plaintext 12.775 ns 78,279,480.0 +101.9%
GetHeaders preview4 Common 121.355 ns 8,240,299.3
GetHeaders preview5 Common 37.598 ns 26,597,474.6 +222.8%
GetHeaders preview4 Unknown 366.456 ns 2,728,840.7
GetHeaders preview5 Unknown 223.472 ns 4,474,824.0 +64.0%
SetHeaders preview4 Plaintext 49.324 ns 20,273,931.8
SetHeaders preview5 Plaintext 34.996 ns 28,574,778.8 +40.9%
SetHeaders preview4 Common 635.060 ns 1,574,654.3
SetHeaders preview5 Common 108.041 ns 9,255,723.7 +487.7%
SetHeaders preview4 Unknown 1,439.945 ns 694,470.8
SetHeaders preview5 Unknown 517.067 ns 1,933,985.7 +178.4%

Configurable unconsumed incoming buffer size for IIS

Prior to this change, the IIS server only buffered 64 KiB of unconsumed request bodies. This resulted in reads being constrained to that maximum size, which impacts the performance when large incoming bodies such as large uploads. In .NET 6 Preview 5, we’ve changed the default buffer size from 64 KiB to 1 MiB which should result in improved 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, we’ve also made the buffer size configurable, allowing you to tune it based on your workload.

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<IISServerOptions>(
        options =>
        {
            options.MaxRequestBodySize = 64 * 1024;
        }
    );
}

Give feedback

We hope you enjoy this preview release of ASP.NET Core in .NET 6. We’re eager to hear about your experiences with this release. Let us know what you think by filing issues on GitHub.

Thanks for trying out ASP.NET Core!

Author

Daniel Roth
Principal Product Manager

Daniel Roth is a Program Manager on the ASP.NET team at Microsoft.

53 comments

Discussion is closed. Login to edit/delete existing comments.

  • dwkrp

    Thank you for the great MAUI and Blazor work. So awesome! I am curious if there is any way to also host Kestrel in a MAUI Blazor app so we could include some HTTP Controllers in the same process?

    • Daniel RothMicrosoft employee Author

      Yup, hosting ASP.NET Core & Kestrel in a .NET MAUI process should be fine. If you run into any issues with it, let us know!

      • dwkrp · Edited

        Thank you Daniel. Should I expect the following to work? (i.e. adding ConfigureWebHostDefaults into the MAUI startup class)

        <code>

        At runtime I get an exception that the 'configuration' parameter cannot be null...

        at Microsoft.AspNetCore.Hosting.WebHostOptions..ctor(IConfiguration configuration, String applicationNameFallback)
        at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.GetWebHostBuilderContext(HostBuilderContext context)
        at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.<.ctor>b__6_1(HostBuilderContext context, IConfigurationBuilder configurationBuilder)
        at Microsoft.Maui.Hosting.AppHostBuilder.BuildAppConfiguration()
        at Microsoft.Maui.Hosting.AppHostBuilder.Build()
        at Microsoft.Maui.MauiWinUIApplication.OnLaunched(LaunchActivatedEventArgs args)
        at maui.blazor.WinUI.App.OnLaunched(LaunchActivatedEventArgs args) in ~project-path~\Platforms\Windows\App.xaml.cs:line 29
        ...

        Read more
      • Daniel RothMicrosoft employee Author

        Looks like .NET MAUI doesn’t provide an IConfiguration service, so you’ll need to add that. Also, while this should be fine on desktop I don’t know that you’ll be able to get ASP.NET Core to work on iOS or Android.

  • Rod Macdonald

    Hi Daniel, with the new Windows 11 store on the horizon, can I please ask what the deployment scenario(s) will be for Blazor moving forwards and whether Blazor’s PWA capabilities will match those of the announced PWAbuilder. Thank you.

  • Rui Lima

    Blazor AOT is generating a huge dotnet.wasm (106,640K) vs the non AOT of (2,172K), this is a big killer. I must be missing something.

    • Daniel RothMicrosoft employee Author

      Hi Rui. That is surprisingly large! What is the total size of the .NET assemblies downloaded by your app when you don’t use AOT compilation?

      • Rui Lima · Edited

        Hi Daniel, with dotnet 5: 13.02 MB / 3.99 MB transferred
        I haven’t deployed yet with dotnet 6.

        Doing the publish locally from VS2019 latest preview
        the wwwroot/_framework has:
        AOT: 174 MB
        non AOT: 33.0 MB

        pic with file properties window:
        https://ibb.co/Sc8MftY

        global.json:
        {
        “sdk”: {
        “version”: “6.0.100-preview.5.21302.13”
        }
        }

      • Rui Lima

        Over the weekend I’ll try to see if I can create a sample project that present the same symptoms.
        Unfortunately, I cannot share the project where I am seeing this. If I manage to recreate the issue I will open the new github issue and add the sample project there.

  • piercarlo schiavo · Edited

    Hello,
    after upgrade the preview 4 to 5 I have following beared authentication problem:

    <code>

    I'm using WebAssembly Hosted blazor App, where I applied authentication:

    <code>

    Thankyou for tips

    Piercarlo

    Read more
    • piercarlo schiavo

      Ok,
      Installed the new “preview 6” and error was resolved.

      Piercarlo

  • Stk

    I just wanna thank the whole Blazor team for the amazing work you are doing.

    We have already ported 5 React + . NET api solutions and the development speed is amazing while having a blast.

    Blazor is for sure the future. Rock on!

    • Daniel RothMicrosoft employee Author

      Awesome! That’s great to hear!

  • Stevie White

    We started using Blazor for a couple of projects at my company this year and I can say that it has been a tremendous help for all of us. Coming from a Vue/Angular/Xaml/MVC background, it felt super intuitive. Personally, I have been following the project since Steve first started talking about Blazor, which now feels like last week (man time has flown)!

    Anyways, I'm super happy with the speed that Blazor has developed, and I am...

    Read more
    • Daniel RothMicrosoft employee Author

      Thanks Stephen! It’s great to hear that Blazor is working out for you!

  • Rod Macdonald · Edited

    Having been overly cautious regarding getting started with Blazor, I'm finally convinced it's a superb framework with a brilliant feature set and community adoption which seems to be getting better and better by the day. I plan to use it desktop and web server. Two things:

    I fired up preview 4 three or so days ago to run an out of the box MAUI Blazor desktop instance. The desktop app seems to load but the...

    Read more
    • Stevie White

      Hey Rod,

      I had the same question about BlazorDay (I forgot it was today, lol). I found the recording that includes Dan’s presentation on Youtube at this link..

      • Rod Macdonald · Edited

        Thanks Stephen, had managed to click on the video for 2020 where of course Dan is featured at the start and not the finish, dohhhh!

        postback: Just seen the video – awesome presentation!

  • Steve Wasielewski

    Try to install "dotnet workload install microsoft-net-sdk-blazorwebassembly-aot" and getting the following error:

    System.IO.FileNotFoundException: Could not find file 'C:\Program Files\dotnet\sdk-manifests\6.0.100\Microsoft.NET.Workload.Android\WorkloadManifest.json'.
    File name: 'C:\Program Files\dotnet\sdk-manifests\6.0.100\Microsoft.NET.Workload.Android\WorkloadManifest.json'
    at System.IO.Strategies.FileStreamHelpers.ValidateFileHandle(SafeFileHandle fileHandle, String path, Boolean useAsyncIO) in System.Private.CoreLib.dll:token 0x6005b95+0x27
    at System.IO.Strategies.FileStreamHelpers.CreateFileOpenHandle(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize) in System.Private.CoreLib.dll:token 0x6005b8f+0x7a
    at System.IO.Strategies.WindowsFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize) in System.Private.CoreLib.dll:token 0x6005c4f+0x23
    ...

    Read more
    • Daniel RothMicrosoft employee Author · Edited

      Hi Steve. I'm sorry you're hitting issues! There are some known problems with workload installation in this release. Did you install .NET 6 Preview 5 via Visual Studio 2022 Preview 1? Or did you use the standalone installer for .NET 6 Preview 5?

      Also, if you've installed .NET MAUI previously with .NET 6 Preview 4, could you please try updating the tool and running again? This may help clean up the workloads.

      Read more
      • Daniel RothMicrosoft employee Author

        This issue happens because some of the workloads were renamed in .NET 5 Preview 5. To work around this issue:

        In the .NET SDK installation folder, delete all folders under sdk-manifests\6.0.100 (for example, under C:\Program Files\dotnet\sdk-manifests\6.0.100) that have the form Microsoft.NET.Workload.*, EXCEPT for microsoft.net.workload.mono.toolchain.

      • AlanW

        this comment has been deleted.

  • Yasser SASSI

    is hot reload works with *.razor pages now ?

    • Daniel RothMicrosoft employee Author

      Hi Yasser. .NET Hot Reload works with .razor files when using dotnet watch, but isn’t enabled in Visual Studio yet. That’s coming in a future Visual Studio update.

      • Pavel Tamkovich

        dotnet watch for Blazor WebAssembly (didn’t test for other projects) doesn’t work at all. “watch : File changed: bla bla bla” and that’s all what I have. Page doesn’t reload\update, but also with manual reload I don’t have updated code. Please check and fix it.

      • Daniel RothMicrosoft employee Author

        Hi Pavel. I'm sorry isn't working for you! We'll need some more details on how to reproduce the issue you are seeing. When I try out with a default Blazor WebAssembly app in .NET 6 Preview 5 it seems to work. Could you please file a GitHub issue with details on the exact steps that you are trying that leads to this issue?: https://github.com/dotnet/aspnetcore/issues/new.

        Read more
  • Steven Hanquez

    I migrated my WebAPI project from Net5 to Net6.

    However, I am unable to update the "Microsoft.VisualStudio.Web.CodeGeneration.Design" package from "version 6.0.0 preview 4" to "version 6.0.0 preview 5".

    I get this errors messages:
    Error Package restore failed. Rolling back package changes for 'GMAO.Services.WebApi'.
    Error NU1102 Unable to find package System.ComponentModel.Annotations with version (>= 6.0.0-preview.5.21217.1)
    - Found 57 version(s) in nuget.org [ Nearest version: 6.0.0-preview.4.21253.7 ]
    - Found 2...

    Read more
    • Daniel RothMicrosoft employee Author

      Thanks for bringing this to our attention! Looks like a System.ComponentModel.Annotations didn’t get updated for .NET 6 Preview 5. We’re looking into it.

      • Daniel RothMicrosoft employee Author

        Turns out not publishing System.ComponentModel.Annotations for .NET 6 Preview 5 was intentional, because it has been moved into the shared framework. The Microsoft.VisualStudio.Web.CodeGeneration.Design package needs to be republished without this package reference, which we are working on.

      • Steven Hanquez

        It’s ok for me 🙂

      • Daniel RothMicrosoft employee Author

        OK, Microsoft.VisualStudio.Web.CodeGeneration.Design was republished with the fix. Please give it a try and let us know if you’re still hitting issues.

      • Steven Hanquez

        Good news 🙂 Thanks for the reply.