Microsoft starts with previews for .NET 11.0
Two months after .NET 10.0, Microsoft starts preview series for version 11, primarily with innovations in the web frontend framework Blazor.
(Image: Pincasso/Shutterstock.com)
- Dr. Holger Schwichtenberg
.NET 11.0 is now available fresh for download, as usual with three runtime variants and an SDK that reports version 11.0.100-preview.1.26104.118 after installation.
At the same time, updates for Visual Studio have also been released: Visual Studio 2022 has reached version 17.14.26, Visual Studio 2026 is at version 18.3.0, and the Insiders version is at 11506.43.
None of these Visual Studio versions include .NET 11.0, but after separately installing the .NET 11.0 SDK, .NET 11.0 is available as an option in the Insider version. A quick test revealed that .NET 11.0 applications cannot be compiled in the other Visual Studio versions.
New Controls in Blazor
Microsoft has added three new components to Blazor: Firstly, the <EnvironmentBoundary> component allows HTML output to be dependent on the host environment (Development, Staging, and Production). Developers can control in which environments output occurs via the Include and Exclude parameters. ASP.NET MVC and Razor Pages already had a Tag Helper for this. In Blazor, one had to work with @if conditions.
The following code uses the new Blazor component <EnvironmentBoundary>:
<EnvironmentBoundary Include="Development,Staging">
<div class="alert alert-warning">
<p>Debug oder Staging</p>
</div>
</EnvironmentBoundary>
<EnvironmentBoundary Exclude="Production">
<p>@DateTime.Now</p>
</EnvironmentBoundary>
The other two new Blazor components are called <Label> and <DisplayName>. They are also counterparts to existing functions in the older web frameworks. Both components deal with labeling form fields. In Blazor forms, developers previously had to enter labels manually using HTML tags:
<div>
<label for="companyName">Firma</label>
<InputText class="form-control" id="customerFullName" @bind-Value="company.CompanyName" />
<ValidationMessage For="@(() => company.CompanyName)" />
</div>
Even if there were data annotations in the object model, such as:
<QuickGrid
OnRowClick="@HandleRowClick"
ItemsProvider="@itemsProvider"
TGridItem="BO.WWWings.Flight" …>
Now, Blazor can retrieve the appropriate display name from the object model with <DisplayName>:
<label for="companyName"> <DisplayName For="() => company.CompanyName" /></label>
The <Label> component allows further shortening to
<Label For="() => company.CompanyName" />
Embedding an input control within <Label> is also possible:
<Label For="() => company.CompanyName" >
<InputText class="form-control" id="customerFullName" @bind-Value="company.CompanyName" />
<ValidationMessage For="@(() => company.CompanyName)" />
</Label>
Furthermore, with Blazor, you can now interactively render Mathematical Markup Language (MathML) to display mathematical formulas in the browser. Previously, Blazor could only generate HTML and SVG.
Enhancements to Existing Functions in Blazor
The existing Blazor control <QuickGrid> in .NET 11.0 Preview 1 gets the new event OnRowClick():
<QuickGrid
OnRowClick="@HandleRowClick"
ItemsProvider="@itemsProvider"
TGridItem="BO.WWWings.Flight" …>
This event can be handled by synchronous or asynchronous methods:
void HandleRowClick(BO.WWWings.Flight f) { …. }
async Task HandleRowClick(BO.WWWings.Flight f) { …. }
OnRowClick() ensures that when the mouse hovers over the rows, the cursor pointer (usually a hand) is displayed.
The built-in <NavLink> component and the NavigationManager helper class now offer relative navigation from the current location in addition to absolute navigation:
<NavLink href="ziel" RelativeToCurrentUri="true">
Zum Ziel
</NavLink>
and
void NavRelative()
{
// Navigate to a sibling page
NavigationManager.NavigateTo("ziel", new NavigationOptions
{
RelativeToCurrentUri = true
});
}
The also new method GetUriWithHash() appends a fragment identifier to the current URL. For example, NavigationManager.GetUriWithHash("Kapitel2") adds #Kapitel2.
Simplified Configuration in Blazor
For Blazor Server, SignalR connection properties can now be set more easily in the Program.cs startup code than before:
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode(options =>
{
options.ConfigureConnection = dispatcherOptions =>
{
dispatcherOptions.CloseOnAuthenticationExpiration = true;
dispatcherOptions.AllowStatefulReconnects = true;
dispatcherOptions.ApplicationMaxBufferSize = 1024 * 1024;
};
});
There are also new improvements for the JavaScript-based part of Blazor configuration for older projects that still use blazor.server.js and blazor.webassembly.js as client libraries. Here, developers can now use the same syntax as with the blazor.web.js client library introduced in .NET 8.0, see the relevant section in the release notes.
Blazor WebAssembly now also supports the IHostedService interface for background services in the web browser and the IConfiguration interface for accessing environment variables.
New Features in the Base Class Library
There are also new features in the base class library that benefit all types of .NET applications. Since .NET Core 3.0, the System.Text.Rune class has been available for simplified handling of Unicode characters outside the Basic Multilingual Plane (BMP). New in .NET 11.0 is that the methods of the System.String and System.Text.StringBuilder classes, as well as System.IO.TextWriter, also accept instances of the Rune class as parameters, for example in IndexOf() and Replace():
string text = "▶ Urbi ⌂ et Orbi 🌍!";
Rune globe = new Rune(127757); // 🌍 127757
int index = text.IndexOf(globe); // 17
string replaced = text.Replace(globe, new Rune('↯')); // "▶ Urbi ⌂ et Orbi ↯!"
With the new RunePosition class, you can list the individual runes in a string:
foreach (RunePosition pos in RunePosition.EnumerateUtf16(text))
{
Console.WriteLine($"Rune: {pos.Rune.Value}, Start: {pos.StartIndex}, Length: {pos.Length}");
}
These lines produce the following output with regard to "Hello 🌍 World":
Rune: 9654, Start: 0, Length: 1
Rune: 32, Start: 1, Length: 1
Rune: 85, Start: 2, Length: 1
Rune: 114, Start: 3, Length: 1
Rune: 98, Start: 4, Length: 1
Rune: 105, Start: 5, Length: 1
Rune: 32, Start: 6, Length: 1
Rune: 8962, Start: 7, Length: 1
Rune: 32, Start: 8, Length: 1
Rune: 101, Start: 9, Length: 1
Rune: 116, Start: 10, Length: 1
Rune: 32, Start: 11, Length: 1
Rune: 79, Start: 12, Length: 1
Rune: 114, Start: 13, Length: 1
Rune: 98, Start: 14, Length: 1
Rune: 105, Start: 15, Length: 1
Rune: 32, Start: 16, Length: 1
Rune: 127757, Start: 17, Length: 2
Rune: 33, Start: 19, Length: 1
In the new assembly System.IO.Compression.Zstandard.dll, Microsoft provides classes for lossless compression using the Zstandard (zstd) compression method developed at Facebook. New classes include System.IO.Compression.ZstandardStream and System.IO.Compression.ZstandardEncoder, as well as System.IO.Compression.ZstandardCompressionOptions. According to Microsoft: "Zstandard compresses 2 to 7 times faster than Brotli and Deflate at optional level 2 and decompresses 2 to 14 times faster at the fastest level, achieving comparable compression ratios." Zstandard can also already be used for HTTP response compression in .NET 11.0.
In the file system classes in the System.IO namespace, the File class now offers the new methods File.CreateHardLink() and FileInfo.CreateAsHardLink() for creating hard links. Previously, developers could only create symbolic links with File.CreateSymbolicLink() since .NET 6.0, but this always required administrator privileges.
Some other new features in the base class library are described in the release notes, including the new floating-point type System.Numerics.BFloat16 and alternative rounding for divisions with the options Truncate, Floor, Ceiling, AwayFromZero, and Euclidean, as well as a new Verify() method in some hash algorithm classes.
Entity Framework Core now supports complex types, including JSON mapping, even in entity classes that use inheritance, as stated in the EF Core 11.0 documentation. However, Table-per-Hierarchy (TPH) inheritance is still excluded.
Parameters for Collection Expressions in C# 15.0
As usual, .NET 11.0 also includes a new C# version, this time numbered 15.0. However, in .NET 11.0 Preview 1, there is only one new language feature for C# 15.0 so far: Collection Expression Arguments. Since C# 12.0, C# has had Collection Expressions for simplified initialization of collections of objects, for example with
List<int> magicNumbers1 = [6, 7, 42];
However, this syntax with square brackets was not possible when setting constructor parameters like the capacity of a collection during initialization:
List<int> magicNumbers2 = new(100) { 6, 7, 42 };
or more expressively
List<int> magicNumbers3 = new(capacity:100) { 6, 7, 42 };
In C# 15.0, this special case can now be expressed with Collection Expression Arguments as follows, although it does not significantly shorten the syntax:
List<int> magicNumbers3 = [with(capacity: 100), 6, 7, 42];
Another improvement to Collection Expressions is in progress at Microsoft for C# 15.0: they should now also be usable for dictionaries, for example with:
SortedDictionary<string, int> dic = ["six":6, "seven":7, "forty two":42];
Improvements in the .NET SDK
If multiple target frameworks are specified in a project, such as in
<TargetFrameworks>net10.0-windows;net11.0-windows</TargetFrameworks>
the .NET command-line command dotnet run will now ask which framework should be used for startup;
Alternatively, the framework can be specified via parameter as before:
dotnet run --framework net11.0-windows
For .NET MAUI on iOS and Android, there are two new parameters for dotnet run: --list-devices and --device. The first parameter lists all devices, the second selects the device at startup. Here too, dotnet run will now prompt interactively if no specification is given.
For Entity Framework Core command-line commands, there is now a new flag parameter -add for Update-Database and dotnet ef database update respectively. It ensures that a schema migration step is created and executed immediately. Previously, one had to call Add-Migration or dotnet ef migrations add first.
Microsoft has improved hot reloading with dotnet watch: Developers can now add project and NuGet package references without restarting the application. For updating browser windows during hot reloading, the port can now be freely chosen via the environment variable DOTNET_WATCH_AUTO_RELOAD_WS_PORT.
In the project settings, you can now control whether .pdb files are generated with <PublishReferenceSymbols>true|false</PublishReferenceSymbols>.
Other New Features and Breaking Changes
More information about .NET 11.0 Preview 1 can be found in a blog post from Microsoft. This includes that .NET-based WebAssembly applications can now use the .NET Core Runtime as an alternative to the Mono Runtime. However, it is stated that this option will only be considered stable in .NET 12.0.
As is customary with every .NET version in recent years, .NET 11.0 will again have breaking changes compared to the previous version 10.0. A few breaking changes are already included in Preview 1.
Outlook
.NET 11.0 is scheduled for release in November 2026 and will have a standard term support of two years. Until then, a total of six more preview versions are expected from March to August, as well as one release candidate version each in September and October.
(mma)