Announcing .NET 8 Release Candidate 1

Leslie Richardson

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

There are several exciting posts you should check out as well:

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:

  1. By adding the RuntimeHostConfigurationOption in the *.csproj file, as demonstrated below:
<ItemGroup>
      <RuntimeHostConfigurationOption Include="Switch.System.Windows.Media.EnableHardwareAccelerationInRdp" Value="true" />
</ItemGroup>
  1. 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.

13 comments

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

  • Lukas 5

    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

    • EoflaOE ViceCity 0

      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:

      URL: https://microsoft.sharepoint.com/teams/VisualStudioProductTeam/_layouts/15/doc2.aspx?sourcedoc=%7B792F3AA9-DA98-4EA1-AA5F-08283AFB074B%7D&file=17.8%20Preview%202%20Blog.docx&action=default&mobileredirect=true&share=IQGpOi95mNqhTqpfCCg6-wdLAcCQFjobo5bUG6j8ybc8HpI
      Issue Type: User not in directory.

      Notice the .docx in the middle of the URL.

    • Jaliya Udagedara 4

      Yeah, still not seeing an update to download Visual Studio 2022 17.8 Preview 2 as well.

    • Leslie RichardsonMicrosoft employee 2

      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.

  • Victor Irzak 4

    Visual Studio 2022 17.8 Preview 2 isn’t exactly there

    • Leslie RichardsonMicrosoft employee 1

      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.

  • Gábor Szabó 4

    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, which I believe might not be in Preview 1. Which would be a bummer seeing as Preview 2 seems to be not live as of yet.

  • Spencer Dahl 2

    Visual Studio 2022 17.8 Preview 2 — Where is it?

    • John Kears 0

      The link provided to Visual Studio Preview 2 does not work. Where is preview 2?

    • Leslie RichardsonMicrosoft employee 0

      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.

  • Jorge Pedraza 0

    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”;
    using var client = new HttpClient();
    IAsyncEnumerable books = await client.GetFromJsonAsAsyncEnumerable(RequestUri);

        await foreach (Book book in books)
        {
        Console.WriteLine($"Read book '{book.title}'");
        }
    }
    

    }

    But it creates an error:
    Error CS1061 ‘IAsyncEnumerable<Program.Book?>’ does not contain a definition for ‘GetAwaiter’ and no accessible extension method ‘GetAwaiter’ accepting a first argument of type ‘IAsyncEnumerable<Program.Book?>’ could be found (are you missing a using directive or an assembly reference?) ConsoleApp3 D:\VS2022Preview\source\repos\ConsoleApp3\ConsoleApp3\Program.cs 9 Active

    Could you please clarify this?
    That’s all for now.

    Regards

  • Guillermo Mazzari 0

    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

  • Andriy Savin 0

    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 hood nor it explains when it should be chosen over a non-streaming API). Thanks.

Feedback usabilla icon