.NET 8 is on the Way! 7 Features that will blow your mind 🤯
Tags: csharp, dotnet, news, programming
Published: 2023-10-18 08:22:10

Howdy, fellow developers! Here’s another exciting journey that we’re about to embark on, exploring the brand new features and updates released in [.NET 8](https://www.bytehide.com/blog/dotnet-8) Release Candidate 1 (RC 1). As the seasoned C# developer I am, I can’t wait to dive into the nitty-gritty details this update has to offer.

From cross-building Windows apps on non-Windows platforms with Win32 resources to enabling hardware acceleration in WPF applications accessed via Remote Desktop Protocol, trust me, there’s a lot here to propel your creativity and efficiency to a whole new level.

Are you ready to decode this beast?

Well, stay tuned and let’s take reap the benefits of these innovations together!

## Enhancements in System.Text.Json

Let’s get to the core stuff and explore what’s new within the System.Text.Json namespace.You’re going to love these exciting additions! Be sure to keep up, we’re going to dive into the latest improvements in the .NET 8 Release Candidate 1 that pertain to System.Text.Json.

### IAsyncEnumerable Stream Support in System.Net.Http.Json

Isn’t it fabulous how developments never cease? RC1 introduces extension methods for streaming deserialization of IAsyncEnumerable.

Let’s take time to appreciate this by looking at a little code snippet, shall we?

```csharp
// Setup the request URI with the placeholder "Example" website
const string RequestUri = "https://api.example.com/shoes";

// create a new HTTP client
using var client = new HttpClient();

// create an IAsyncEnumerable that will fetch Shoe data from the API asynchronously
IAsyncEnumerable<Shoe> shoes = client.GetFromJsonAsAsyncEnumerable<Shoe>(RequestUri);

// asynchronously iterate over the collection of shoes
await foreach (Shoe shoe in shoes)
{
    // write the name of each shoe to the console
    Console.WriteLine($"Just checked out the fabulous '{shoe.name}'");
}

// define a record that represents a shoe with its properties
public record Shoe(int id, string name, string brand, int releasedYear);
```

It’s just like magic, isn’t it?

### Creation of JsonContent via JsonContent.Create

The power of `JsonContent.Create` has taken the limelight and how! Now, you can create `JsonContent` instances using trim safe/source generated contracts.

Here’s a little demo just for you.

```csharp
// create a new instance of Shoe with specified properties
var shoe = new Shoe(id: 17, "Air Max", "Nike", releasedYear: 2024);

// convert the shoe object to HttpContent using JsonContent.Create() method and the context for Shoe
HttpContent content = JsonContent.Create(shoe, MyContext.Default.Shoe);

// define a record that represents a shoe with its properties
public record Shoe(int id, string name, string brand, int releasedYear);

// define a class that includes attribute to make Shoe json serializable.
[JsonSerializable(typeof(Shoe))]
public partial class MyContext : JsonSerializerContext 
{ 

}
```

### Parse JsonNode Instances with JsonNode.ParseAsync

One of the top highlights in their [array](https://www.bytehide.com/blog/array-csharp) of features is the newly introduced capability of parsing `JsonNode` instances from streams.

The process of data parsing, traditionally a complicated concept to grasp, has now been made simpler and smoother with our cutting-edge mechanism that can parse `JsonNode` instances directly from streams.

The excitement this feature is garnering isn’t surprising when you consider its potential to streamline the parsing process, an advantage clearly discernible to anyone who takes a moment to study the code.

```csharp
// Open the shoe file with read-only access 
using var stream = File.OpenRead("myShoeCollection.json");

// Parse the content of the shoe file asynchronously into a JsonNode
JsonNode node = await JsonNode.ParseAsync(stream);
```

### JsonSerializerOptions.MakeReadOnly(bool populateMissingResolver) Enhancement

You know the good old `JsonSerializerOptions.MakeReadOnly()` method, right? Well, there have been a few tweaks to make it more trim conservative.

But don’t just jump right into using it, there’s a tiny change. It’ll now throw an [exception](https://www.bytehide.com/blog/5-good-practices-for-error-handling-in-c) if the options aren’t kitted out with a resolver. Yeah, you heard it right! No resolver? You’re crashing with an exception!

Okay, just to stick with our shoe theme, let’s think of this as tailoring a cool shoe design when we’ve got a final production run. We’re adding some comments to explain and keep on track. Here it is:

```csharp
// Begin Property Group. Think of this as starting a new design for our shoe line
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">

  // This is our final production run, analogous to the 'Release' phase
  // In this phase, we want to apply the AndroidStripILAfterAOT. Imagine it as a final touch on our shoe design - trimming away the extras!
  <AndroidStripILAfterAOT>true</AndroidStripILAfterAOT>

</PropertyGroup> // End the Property Group. Our shoe design is complete!
```

With this, your brand new cool shoe design is ready for the final production run! It’s been designed, tested, and finally ready to be strutted on the fashion runway.

Done this way, if there’s no resolver, the method will say “No problem buddy! I’ve got your back!” And bam, it’ll assign the standard [reflection](https://www.bytehide.com/blog/reflection-csharp) resolver to the option. It’s like a safety net in case you forgot to specify a resolver.

## AndroidStripILAfterAOT mode on Android

Wondering what’s new when it comes to Android application development in .NET? Hold on to your hats, folks, because I’m about to share something game-changing! Come on board as we explore the `AndroidStripILAfterAOT` setting on Android.

Do you know what happened with .NET 6 and onwards? They implemented this cool thing called Profiled Ahead-of-Time (or AOT, if you want to sound all techy) compilation mode. It’s pretty sophisticated: whenever you’re building an application in ‘Release’ mode, it automatically starts using this new mode.

So why the big fuss, you ask? Well, let me tell you, it’s because of the huge improvements it brings to the table. For starters, your app starts running like greased lightning, and the performance during runtime is just phenomenal. It’s like upgrading from a tricycle to a Ferrari!

But, hang on a minute, before you start popping champagne, there’s a small catch. When AOT compilation is put to use, the size of your application tends to pump up. You might think of it as a trade-off, but it’s not necessarily a bad thing. Size doesn’t always matter, right?

Well, our saviour here is the specific way the profiled AOT works – it doesn’t just go compiling everything left, right, and centre. Instead, it chooses specific bits of your app’s launch path to compile.

This method accelerates startup times while only slightly expanding the application size. So, how can one tackle this issue of inflated size? The solution lies in `AndroidStripILAfterAOT`, a recent addition to the .NET functionalities.

It reduces unused Intermediate Language (IL) that was compiled using AOT, and therefore decreases the application package (apk) size. This can result in a significant size reduction between 0 and 3.5% for an application built from a dotnet template application.

### When and why you should use AndroidStripILAfterAOT:

Let’s face it, when developing Android applications, performance often takes precedence over everything else. If you are willing to allow for a slight uptick in app size in favor of enhanced performance, taking the AOT-compilation route for all the code is a smart move. The introduction of `$(AndroidStripILAfterAOT)` advances this approach a step further.

This feature eliminates the unused Intermediate Language (IL), making any surge in app size due to AOT-compilation more manageable. An added advantage is that the removal of this unused IL can bolster your application’s .NET code security.

However, keep in mind that although it strengthens the code, it does not make it completely secure against reverse-engineering tactics.

### AndroidStripILAfterAOT usage:

Want to test drive it yourself? Incorporate the following MsBuild property for your Android app:

```csharp
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
  <AndroidStripILAfterAOT>true</AndroidStripILAfterAOT>
</PropertyGroup>
```

By setting `AndroidStripILAfterAOT` to true, you’ll override the existing `AndroidEnableProfiledAot` setting and all trim-able AOT’d methods get shown the door. Profiled AOT and IL stripping can work in harmony when setting both explicitly:

```csharp
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
  <AndroidStripILAfterAOT>true</AndroidStripILAfterAOT>
  <AndroidEnableProfiledAot>true</AndroidEnableProfiledAot>
</PropertyGroup>
```

Now, let’s compare apk sizes for a `dotnet new android` app [under different configurations](https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-rc1/):

![bytehide.com](https://www.bytehide.com/_next/image?url=https%3A%2F%2Fardounco.sirv.com%2FWP_content.bytehide.com%2F2023%2F10%2Fimage.png&w=3840&q=75)


For the record, when you have `$(AndroidStripILAfterAOT)` set to false and `$(AndroidEnableProfiledAot)` set to true, you’re going with the default Release configuration environment and your app will stand at 7.7MB.

### A Closing Thought…

So, excited to get stuck into these new features? I sure am! It would be great to get your feedback. If you stumble on any bugs or issues, please file them directly at the [dotnet/runtime repository](https://github.com/dotnet/runtime). Your input will help us make this feature even more user-friendly. Start exploring and let’s keep improving together!

## Change in Tagging Pattern for .NET Containers

As we get closer to the General Availability (GA) release of .NET 8, an essential amendment has taken place in the .NET container images. Ready for what’s new? Say goodbye to the “preview” in the tag name for RC 1 and we’ll walk you through the changes.

In the previous preview versions of .NET 8, we published the floating tags as `8.0-preview` and `8.0-preview-<OS>`. Well, from the RC 1 release onwards, we won’t maintain these tags. You may now be wondering what you should do instead. Well, simply replace your tag references with `8.0` and `8.0-<OS>`. Sound easy, right?

What’s the rationale behind the change, you ask? This transition ensures a smooth sailing journey towards the GA release of .NET 8. Moreover, these are set to be the permanent tags maintained throughout the lifecycle of .NET 8.

## Non-Windows Platforms can Now Cross-Build Windows Apps with Win32 Resources

Do you happen to create Windows apps from non-Windows platforms? This is going to be your favorite. Now imagine this, you’re building applications meant for Windows but on non-Windows platforms.

Any recognized Win32 resources get seamlessly integrated into the resulting executable. A sigh of relief for cross-building aficionados, isn’t it?

We’re talking about things like your application icon, manifest, and version information. Cool, right?

In the past, to get these resources, applications had to be built on Windows. Eliminating this gap in cross-building support was a high demand, as it majorly alleviated issues related to infrastructure complexity and resource usage. Goodbye to those pain points and say hello to more efficient cross-building!

## Azure Managed Identity Now Supported for SDK Container Publishing

Alright everyone, sit tight because I’ve got some groundbreaking news that will make your developer hearts sing! Remember how it used to be such a task to [convert .NET applications to containers](https://learn.microsoft.com/dotnet/core/docker/publish-as-container) and then pushing these containers off to registries like Docker Hub and Azure Container Registry? Well, those days are over, my friends, thanks to the fantastic SDK Container publish feature!

Now, I’m sure you’re no stranger to the fun and games we usually have when it comes to authenticating this sort of procedure. Most of the time, we’re stuck using that `docker login` command, right?

However, there was always a catch when dealing with certain registries like Azure Container Registry – they aren’t into ordinary usernames & passwords. No siree, they instead kick it up a notch and use OAuth token exchange for authentication. Unfortunately, our poor old SDK Container publishing tools struggled to deal with this level of sophistication.

Let’s get the confetti out because our long-awaited hero is here – the .NET 8.0.100 RC1! Starting today, our SDK Container publishing tool is totally cool with OAuth token exchange authentication method! Yeah, hard to believe, isn’t it? Finally, Azure Container Registry and other registries using the same method are now fair game!

```csharp
> az acr login -n <your registry name>
> dotnet publish -r linux-x64 -p PublishProfile=DefaultContainer
```

## WasmStripILAfterAOT Mode on WASM

Any Blazor WebAssembly aficionados out there? If you use often WASM Browser, this one’s for you! Both platforms now support ahead-of-time (AOT) compilation where you can directly compile your .NET code into WebAssembly.

AOT compilation does come with its perks – it boosts runtime performance. But, as a caveat, it also results in larger app sizes. With the new `WasmStripILAfterAOT` mode, we can slice the size of the \_framework folder by a nifty 1.7% – 4.2%. If you’re curious about how we arrived at these figures, check out the above Github issue.

### Is WasmStripILAfterAOT Right for You?

Trust me when I say, this feature is a superstar whenever you go for AOT compilation. Smaller app size, and same stellar performance? Yeah, give it a shot!

### Get Started with WasmStripILAfterAOT:

Ready to whip this tool into action? Set the following MsBuild property for your Blazor WebAssembly or WASM Browser app:

```csharp
<PropertyGroup>
  <RunAOTCompilation>true</RunAOTCompilation>
  <WasmStripILAfterAOT>true</WasmStripILAfterAOT>
</PropertyGroup>
```

By using this command, a large portion of the Intermediate Language (IL) code from both the built-in libraries and the code written by you splendid application developers will be chopped off. It’s like a neat little trim for your code to make it sleeker and more efficient.

## WPF Hardware Acceleration in Remote Desktop Protocol

Hey there, WPF fans! Have you ever been working remotely, using a WPF application, and thought: “Man, I wish this thing had sharper visuals?” Well, it’s your lucky day because we’ve got just the update you’ve been dreaming of!

Back in the day, you used to only have the option of software rendering, even when accessing your WPF applications remotely. Remember how frustrating that was? You’d have a beast of a machine capable of hardware rendering, but still being forced to settle for software rendering… a total bummer!

Well, forget all that because we’re stirring things up with an amazing new feature that empowers developers to leverage the pure power of hardware acceleration when using the Remote Desktop Protocol (RDP). No more limitations, and no more settling for less. You just flip an AppContext switch and voilà, you are all set!

Scratching your head wondering what the heck this hardware acceleration gibberish is? Let me break it down for you. Hardware acceleration is when we let your computer’s graphic processing unit (GPU) take the reins. This GPU speeds up the creation of visuals and graphics within your WPF application.

So, what can you expect? A smooth, captivating visual experience that looks sweet and runs buttery smooth—quite the upgrade from software rendering, where your computer’s central processing unit (CPU) did all the heavy lifting. This old-school method was slower, not super efficient and let’s be honest, a total vibe killer.

### Hardware Acceleration in RDP for Your WPF App:

Alright, let’s get down to the nitty-gritty. How do you actually switch on this hardware acceleration feature in RDP? Well, my friends, you have not one but two ways to get this done, because who doesn’t like a little flexibility and choice, right?

-   The first way is by introducing the `RuntimeHostConfigurationOption` into your handy dandy `*.csproj` file, as demonstrated in the following code snippet.

```csharp
<ItemGroup>
      <RuntimeHostConfigurationOption Include="Switch.System.Windows.Media.EnableHardwareAccelerationInRdp" Value="true" />
</ItemGroup>
```

-   By adding the `configProperty` in the `*.runtimeconfig.json` file, as illuminated below:

```csharp
 "configProperties": {
      "Switch.System.Windows.Media.EnableHardwareAccelerationInRdp": true
    } 
```

### Last Bit of Wisdom:

Gear up, folks, and test drive this fresh-off-the-lab feature. And should you stumble upon any glitches along the way, don’t hesitate to reach out. Got a bug to report or feedback to give? Send them directly to our [dotnet/wpf repository](https://github.com/dotnet/wpf). We’re eager to hear from you, because together, we’re only going to make the experience even better!

## Fast Recap

So there you have it, a deep dive into the world of .NET 8 Release Candidate 1. I hope you found this useful and picked up a trick or two to implement in your projects. Remember, innovation and updates are always part of the developer’s lifecycle. Keep exploring, keep learning, and don’t forget to have fun while coding!

Till next time, keep your code clean, your bugs minimal, and your passion for coding aflame. Happy coding, folks! Remember, the game is about continuously improving, adapting to changes and staying ahead – and there is no better way to do that than embracing every new update that comes your way.

So, stay tuned for more engaging content, updates, and development adventures.