.NET 8 RC1 is now available. This is our first of two release candidates. This release includes a new AOT mode for both Android and WASM, System.Text.Json improvements, and Azure Managed Identity support for containers. Now is great time to pick up and test .NET 8 if you haven’t yet.
The dates for .NET Conf 2023 have been announced! Join us November 14-16, 2023 to celebrate the .NET 8 release!
Download .NET 8 RC1 for Linux, macOS, and Windows.
- Installers and binaries
- Container images
- Release notes
- Breaking changes
- Known issues
- GitHub issue tracker
There are several exciting posts you should check out as well:
- ASP.NET Core Updates in .NET 8 RC1
- .NET MAUI Updates in .NET 8 RC1
- Visual Studio 2022 17.8 Preview 2
- Entity Framework Updates in .NET 8 RC1
- What’s New in .NET 8 describes all the new features in .NET 8. For a broader view of the platform, read Why .NET?.
System.Text.Json Improvements
System.Net.Http.Json
extensions for IAsyncEnumerable
https://github.com/dotnet/runtime/pull/89258
RC1 sees the inclusion of IAsyncEnumerable streaming deserialization extension methods:
const string RequestUri = "https://api.contoso.com/books";
using var client = new HttpClient();
IAsyncEnumerable<Book> books = client.GetFromJsonAsAsyncEnumerable<Book>(RequestUri);
await foreach (Book book in books)
{
Console.WriteLine($"Read book '{book.title}'");
}
public record Book(int id, string title, string author, int publishedYear);
Credit to @IEvangelist for contributing the implementation.
JsonContent.Create
overloads accepting JsonTypeInfo
https://github.com/dotnet/runtime/pull/89614
It is now possible to create JsonContent
instances using trim safe/source generated contracts:
var book = new Book(id: 42, "Title", "Author", publishedYear: 2023);
HttpContent content = JsonContent.Create(book, MyContext.Default.Book);
public record Book(int id, string title, string author, int publishedYear);
[JsonSerializable(typeof(Book))]
public partial class MyContext : JsonSerializerContext
{ }
Credit to @brantburnett for contributing the implementation.
JsonNode.ParseAsync
APIs
https://github.com/dotnet/runtime/pull/90006
Adds support for parsing JsonNode
instances from streams:
using var stream = File.OpenRead("myFile.json");
JsonNode node = await JsonNode.ParseAsync(stream);
Credit to @DoctorKrolic for contributing the implementation.
JsonSerializerOptions.MakeReadOnly(bool populateMissingResolver)
https://github.com/dotnet/runtime/pull/90013
The existing parameterless JsonSerializerOptions.MakeReadOnly()
method was designed to be trim-safe and will therefore throw an exception in cases where the options instance hasn’t been configured with a resolver.
Calling the new overload with
options.MakeReadOnly(populateMissingResolver: true);
will populate the options instance with the default reflection resolver if one is missing. This emulates the initialisation logic employed by the JsonSerializer
methods that accept JsonSerializerOptions
. A side-effect of that behavior is that the new overload is marked RequiresUnreferenceCode
/RequiresDynamicCode
and is therefore unsuitable for Native AOT applications.
AndroidStripILAfterAOT
mode on Android
https://github.com/xamarin/xamarin-android/pull/8172
We try to choose the best the default configuration for .NET and .NET MAUI applications out of the box. In .NET 6 and higher, specifically, these applications now utilize profiled ahead-of-time (AOT) compilation mode by default when they are built in Release
mode. AOT compilation results in faster startup time and runtime performance improvements at the expense of a larger app size. Profiled AOT, only AOT compiles a portion of your application’s startup path — improving startup time, with a minimal increase to application size. The new AndroidStripILAfterAOT
setting removes unused IL that was AOT-compiled, reducing the apk size by at least 0 – 3.5% for a dotnet template application.
When to consider using AndroidStripILAfterAOT
:
If performance is more of a concern for your Android application than app size, AOT-compiling all code is a great way to achieve the best startup and runtime performance. $(AndroidStripILAfterAOT)
goes a step further to remove the unused IL, making the app size increase from AOT-compilation more reasonable. The removed IL will also no longer be present, making it more difficult (but not impossible) to reverse engineer your application’s .NET code.
How to use AndroidStripILAfterAOT
:
Set the following MsBuild property for your Android app:
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<AndroidStripILAfterAOT>true</AndroidStripILAfterAOT>
</PropertyGroup>
By default setting AndroidStripILAfterAOT
to true will override the default AndroidEnableProfiledAot
setting, allowing all trimmable AOT’d methods to be removed. Profiled AOT and IL stripping can be used together by explicitly setting both:
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<AndroidStripILAfterAOT>true</AndroidStripILAfterAOT>
<AndroidEnableProfiledAot>true</AndroidEnableProfiledAot>
</PropertyGroup>
.apk
size results for a dotnet new android
app:
$(AndroidStripILAfterAOT) |
$(AndroidEnableProfiledAot) |
.apk size |
---|---|---|
true | true | 7.7MB |
false | true | 7.7MB |
true | false | 8.1MB |
false | false | 8.4MB |
Note that $(AndroidStripILAfterAOT)
=false and $(AndroidEnableProfiledAot)
=true is the default Release configuration environment, for 7.7MB.
Limitations:
Not all of the AOT-compiled methods are able to be removed. At runtime, there are various scenarios where we have to switch from AOT to JIT to produce the correct result. With that said, we will be continuously working on reducing gaps in the upcoming .NET 9 release.
Final note
We would like to invite everyone to try out this new feature and file any discovered issues to help us improve the user experience further. Issues can be filed directly to dotnet/runtime repository.
Configuration Binding Generator breaking change
The configuration binding generator has switched to using the compiler interceptors preview feature to emit binding logic – https://github.com/dotnet/runtime/pull/90835.
In non Web SDK scenarios (i.e. apps that require a Microsoft.Extensions.Configuration.Binder
package reference for binding, like console apps), the following additional MSBuild property is now required to enable the generator:
<PropertyGroup>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
+ <Features>$(Features);InterceptorsPreview</Features>
</PropertyGroup>
This is temporary. In RC-2, enabling the generator will switch back to only requiring the one gesture. The compiler inceptors feature will be enabled implicitly in a reliable way.
<PropertyGroup>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
- <Features>$(Features);InterceptorsPreview</Features>
</PropertyGroup>
Containers switch to non-preview tagging pattern
Issue: https://github.com/dotnet/dotnet-docker/issues/4772 PR: https://github.com/dotnet/dotnet-docker/pull/4817
In preparation for the GA release of .NET 8, the .NET container images have switched to a new tagging pattern for RC 1 that removes “preview” from the tag name.
In previous preview releases of .NET 8, floating tags were published with the name of 8.0-preview
and 8.0-preview-<OS>
. These will no longer be maintained starting with the RC 1 release. Instead, you should migrate your tag references to 8.0
or 8.0-<OS>
. Making this change will allow for a seamless transition upon the GA release of .NET 8 as these will be the permanent tags that will be maintained throughout the lifetime of .NET 8.
Cross-building Windows apps with Win32 resources on non-Windows
Issue: https://github.com/dotnet/runtime/issues/3828 PR: https://github.com/dotnet/runtime/pull/89303
Many thanks to @anatawa12 for this great contribution!
When building applications targeting Windows on non-Windows platforms, the resulting executable is now updated with any specified Win32 resources – for example, application icon, manifest, version information.
Previously, applications had to be built on Windows in order to have such resources. Fixing this gap in cross-building support has been a popular request, as it was a significant pain point affecting both infrastructure complexity and resource usage.
SDK: Container publishing now supports Azure Managed Identity
The SDK Container publish feature is an easy way to package .NET applications into containers and push them to container registries like Docker Hub, Azure Container Registry, or other popular registries. Pushing to these remote registries often requires authentication, which is usually handled by the docker login
command. Some registries, like Azure Container Registry, don’t use a standard username/password setup and instead rely on an OAuth token exchange. The SDK Container publishing tools didn’t know how to handle this token exchange, and so users that used Managed Identity on Azure Container Registry (or used any other registry that used Identity Token exchange) would encounter authentication errors when pushing their containers. With .NET 8.0.100 RC1 we’re happy to announce that we now support the OAuth token exchange authentication method, so ACR and all other registries that use it now just work. A typical publishing flow might now look like:
> az acr login -n <your registry name>
> dotnet publish -r linux-x64 -p PublishProfile=DefaultContainer
Doesn’t get much simpler than that! You can learn more about registry authentication in our docs, and you learn how to get started containerizing your apps as well.
WasmStripILAfterAOT
mode on WASM
https://github.com/dotnet/runtime/pull/88926
Blazor WebAssembly and WASM Browser support 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. This new stripping mode reduces the size of _framework folder by 1.7% – 4.2%, based on the testing we’ve done mentioned in the above github issue.
When to consider using WasmStripILAfterAOT
:
This feature is ideal any time you enable AOT compilation, so give it a try for a smaller application!
How to use WasmStripILAfterAOT
:
Set the following MsBuild property for your Blazor WebAssembly or WASM Browser app:
<PropertyGroup>
<RunAOTCompilation>true</RunAOTCompilation>
<WasmStripILAfterAOT>true</WasmStripILAfterAOT>
</PropertyGroup>
It will trim away the IL code for most of the compiled methods, including methods from the libraries and the ones authored by the app developers.
Limitations:
Not all of the compiled methods are trimmable. At runtime, there are various scenarios where we have to switch from AOT to interpreter to produce the correct result. With that said, we will be continuously working on reducing the gap in the upcoming .NET9 release.
Final note
We would like to invite everyone to try out this new feature and file any discovered issues to help us improve the user experience further. Issues can be filed directly to dotnet/runtime repository.
WPF Hardware Acceleration in RDP
https://github.com/dotnet/wpf/pull/7684
In the past, all WPF applications accessed remotely had to use software rendering, even if the system had hardware rendering capabilities. We have added a new option that enables application developers to opt-in for hardware acceleration for RDP by utilizing an AppContext switch.
Hardware acceleration refers to the use of a computer’s graphics processing unit (GPU) to speed up the rendering of graphics and visual effects in an application. This can result in improved performance and more seamless, responsive graphics. In contrast, software rendering relies solely on the computer’s central processing unit (CPU) to render graphics, which can be slower and less effective.
How to enable Hardware Acceleration in RDP for WPF app?
We offer two methods for enabling hardware acceleration in RDP:
- By adding the
RuntimeHostConfigurationOption
in the*.csproj
file, as demonstrated below:
<ItemGroup>
<RuntimeHostConfigurationOption Include="Switch.System.Windows.Media.EnableHardwareAccelerationInRdp" Value="true" />
</ItemGroup>
- By adding the
configProperty
in the*.runtimeconfig.json
file, as shown below:
"configProperties": {
"Switch.System.Windows.Media.EnableHardwareAccelerationInRdp": true
}
Final note
We would like to invite everyone to try out this new feature and file any discovered issues to help us improve the user experience further. Issues can be filed directly to dotnet/wpf repository.
Community Contributor
This month’s community contributer is Jakub Majocha. Here’s a little about him in his own words:
I’m Jakub Majocha. I live in Cracow, Poland where I work in a field unrelated to software. I have a lifelong interest in computer programming but my experience is limited to small one-off scripts, some tools for in-house use and solving programming puzzles like Advent Of Code. I like to chill tinkering with code and I have found F# perfect for this.
The fact that I could just jump in and contribute to F# shows how accommodating the community is. It’s also thanks to the language itself. F#, with its type inference, concise syntax and low ceremony, allows for quick experimentation, refactoring and trying things out. It’s just fun and relaxing.
Summary
The team has transitioned to working on quality and polish as we near the final release in November. Now is a great time to report any issues that you’ve noticed in RC1 and earlier builds. We’d also love to hear your reactions to using these features.
Hi, I have a question regarding GetFromJsonAsAsyncEnumerable. What exactly does it allow to achieve (except for syntactical compatibility with IAsyncEnumerable). E.g, does it allow streamed deserializing of a collection of objects, which otherwise would require to be fully buffered in memory before deserialization could be started? In other words, does it reduce memory allocation in particular? (I know how IAsyncEnumerable works, but just having an API which returns it neither guarantees real streaming under the...
Something nice to see in net8 would be the option of blazor, mvc and maui templates with tailwind instead of bootstrap 🙁 I dont get why Microsoft hasn’t done that yet
Hi. Based on VS Version 17.8.0 Preview 2.0, SDK 8.0.100-rc.1 and .NET Runtime 8.0.0-rc.1
I am trying to compile the next code:
using System.Net.Http.Json;
internal class Program
{
public record Book(int id, string title, string author, int publishedYear);
static async Task Main(string[] args)
{
const string RequestUri = "https://api.contoso.com/books";
...
Visual Studio 2022 17.8 Preview 2 — Where is it?
Hi Spencer and John, VS 17.8 Preview 2 and its corresponding blog post / url should be out very soon so stay tuned and sorry for the confusion.
The link provided to Visual Studio Preview 2 does not work. Where is preview 2?
Cool, we're getting closer to release! I noticed the official download page lists RC1 as go live, and I also noticed there is now a .NET 8 (STS) option available on Azure App Service. I think this is worth calling out.
Does RC1 require Visual Studio 2022 17.8 Preview 2, or will it work well with Preview 1 as well? I guess there would be some IDE-specific enhancements, like support for more page templates in Blazor,...
Visual Studio 2022 17.8 Preview 2 isn’t exactly there
Hi Victor, VS 17.8 Preview 2 and its blog post should be here very soon, so please stay tuned and sorry for the mishap.
Hi,
The vs preview link does not seem to link to a valid page.
The asp.net core RC link goes to the earlier preview url.
Lukas
Hi Lukas, the ASP.NET Core RC Link should be linking to the corresponding RC1 post successfully now. VS 17.8 Preview 2 and the blog post were a tad delayed but should be out very soon, so stay tuned and sorry for the confusion.
Yeah, still not seeing an update to download Visual Studio 2022 17.8 Preview 2 as well.
Can reproduce this. It seems that Visual Studio 2022 17.8 Preview 2 is not ready yet, so that link is actually pointing to an internal Microsoft SharePoint account where it's just basically a link to the draft of the blog.
It says this:
<code>
Notice the .docx in the middle of the URL.