ASP.NET Core in .NET 8 is On The Way! 5 New Features Reviewed
Tags: csharp, dotnet, news, aspdotnet
Published: 2023-04-21 12:41:42

In this article, we delve into the exciting new features and updates introduced in ASP.NET Core .NET 8 Preview 3.

We will explore the addition of ASP.NET Core support for native AOT, server-side rendering with Blazor, rendering Razor components outside of ASP.NET Core, sections support in Blazor, monitoring Blazor Server circuit activity, SIMD enabled by default for Blazor WebAssembly apps, request timeouts, and short circuit routes.

Join us as we take a closer look at these enhancements and how they can improve your web development experience!

## Native AOT in ASP.NET Core

Hold onto your hats! .NET 8 Preview 3 brings Native AOT (Ahead of Time) support for ASP.NET Core, perfect for cloud-native API apps. Now, [publishing an ASP.NET Core app with native AOT](https://learn.microsoft.com/aspnet/core/fundamentals/native-aot) creates a self-contained app AOT compiled to native code. No more need for the .NET runtime on the machine!

### Why native AOT rocks in ASP.NET Core

ASP.NET Core apps with native AOT have a smaller footprint, lightning-fast startup, and use less memory. How cool is that? Plus, the benefits shine in workloads with many instances like cloud infrastructure and massive services.

Native AOT offers:

-   **Smaller disk footprint:** One executable contains the program and used code from external dependencies, leading to smaller container images and quicker deployment.
-   **Faster startup time:** No more JIT compilation means the app is ready in a jiffy, making deployments with container orchestrators a breeze.
-   **Lower memory use:** With less memory needed, you’ll see better deployment density and scalability.

In [Microsoft’s tests](https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-preview-3/#asp-net-core-support-for-native-aot), a simple ASP.NET Core API app with native AOT saw **80%** faster startup time and **87%** smaller app size. That’s a game-changer!

## Minimal APIs Meet Native AOT

Get ready for a fantastic combo! Minimal APIs are now compatible with native AOT, thanks to the Request Delegate Generator (RDG). As a [source generator](https://learn.microsoft.com/dotnet/csharp/roslyn-sdk/source-generators-overview), RDG turns those `MapGet()`, `MapPost()`, and other calls into `RequestDelegate`s with routes during compile-time. No more runtime code generation!

RDG comes to life when you enable native AOT publishing. Want to test your project’s readiness for native AOT or reduce startup time? Manually **enable RDG** with `<EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator>` in your project file.

Minimal APIs love JSON payloads, so the [System.Text.Json](https://learn.microsoft.com/dotnet/standard/serialization/system-text-json/source-generation) [source generator](https://learn.microsoft.com/dotnet/standard/serialization/system-text-json/source-generation) steps in to handle them. Just register a `JsonSerializerContext` with ASP.NET Core’s dependency injection.

Check [Microsoft example](https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-preview-3/#minimal-apis-and-native-aot):

```csharp
// Register the JSON serializer context with DI
builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.AddContext<AppJsonSerializerContext>();
});

...
// Add types used in your Minimal APIs to source generated JSON serializer content
[JsonSerializable(typeof(Todo[]))]
internal partial class AppJsonSerializerContext : JsonSerializerContext
{
}
```

Now you’ve got a powerful mix of Minimal APIs and native AOT!

## Get Started with Native AOT-ready Templates

![a](https://miro.medium.com/v2/resize:fit:700/0*wu008J2opkemgced.png)

_Source: [Microsoft](https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-preview-3/)_

In this preview, Microsoft unveils two native AOT-enabled project templates for ASP.NET Core.

The “ASP.NET Core gRPC Service” template now has an “Enable native AOT publish” option. Tick that box, and `<PublishAot>true</PublishAot>` pops up in your .csproj file.

Introducing the fresh “ASP.NET Core API” template, designed for cloud-native, API-first projects. It’s different from the “Web API” template because it:

-   Only uses Minimal APIs (no MVC yet)
-   Employs `WebApplication.CreateSlimBuilder` for essential features
-   Listens to HTTP only (cloud-native deployments handle HTTPS)
-   Skips IIS or IIS Express launch profiles
-   Enables JSON serializer source generator for native AOT
-   Swaps weather forecast sample for a “Todos API”
-   Temporarily uses [Workstation GC](https://learn.microsoft.com/dotnet/standard/garbage-collection/workstation-server-gc) to minimize memory use

Create a new API project with native AOT using the dotnet CLI:

```csharp
$ dotnet new api -aot
```

The new “ASP.NET Core API” template generates this _Program.cs_ content as you can see in the [Microsoft example](https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-preview-3/#minimal-apis-and-native-aot):

```csharp
using System.Text.Json.Serialization;
using MyApiApplication;

var builder = WebApplication.CreateSlimBuilder(args);
builder.Logging.AddConsole();
builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.AddContext<AppJsonSerializerContext>();
});
var app = builder.Build();
var sampleTodos = TodoGenerator.GenerateTodos().ToArray();
var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>
    sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
        ? Results.Ok(todo)
        : Results.NotFound());
app.Run();
[JsonSerializable(typeof(Todo[]))]
internal partial class AppJsonSerializerContext : JsonSerializerContext
{
}
```

Ready, set, go with native AOT templates!

## Manage Request Timeouts

In this preview release, Microsoft presents a [new middleware](https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-preview-3/#request-timeouts) for handling request timeouts. Now, you can easily set timeouts for specific endpoints, controllers, or on-the-fly per request.

First, add the request timeout services:

```csharp
builder.Services.AddRequestTimeouts();
```

Next, apply request timeouts using middleware with `UseRequestTimeouts()`:

```csharp
app.UseRequestTimeouts();
```

For specific endpoints, use `WithRequestTimeout(timeout)` or add `[RequestTimeout(timeout)]` to the controller or action.

Keep in mind, timeouts are cooperative. When they expire, `HttpContext.RequestAborted` triggers, but requests won’t be forcibly stopped. Your app should keep an eye on the token and decide when to wrap up request processing.

## Quick Route Short Circuit

In this update, [Microsoft introduces a new option for quicker route handling](https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-preview-3/#short-circuit-routes). Usually, when a route matches an endpoint, the middleware pipeline runs before invoking the endpoint logic. However, you might not need this for certain requests, like _robots.txt_ or _favicon.ico_.

Use the `ShortCircuit()` option to immediately invoke the endpoint logic and end the request:

```csharp
app.MapGet("/", () => "Hello World").ShortCircuit();
```

For quickly sending a 404 or another status code without further processing, try `MapShortCircuit`:

```csharp
app.MapShortCircuit(404, "robots.txt", "favicon.ico");
```

This efficient approach bypasses unnecessary features like authentication and CORS.

## Blazor’s Handy Sections

Microsoft introduces `SectionOutlet` and `SectionContent` components in Blazor, making it easy to create content placeholders in layouts. These sections can later be filled by specific pages using unique names or object IDs.

For instance, add a `SectionOutlet` to the top row of `MainLayout` in a Blazor template. Don’t forget to include the `Microsoft.AspNetCore.Components.Sections` directive in the root _\_Imports.razor_ file:

```csharp
@using Microsoft.AspNetCore.Components.Sections
...
<div class="top-row px-4">
    <SectionOutlet SectionName="TopRowSection" />
    <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
```

Now, pages can display content in the `TopRowSection` using `SectionContent`. In _Counter.razor_, you could add a button to increment the counter:

```csharp
<SectionContent SectionName="TopRowSection">
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
</SectionContent>
```

Sections make organizing content a breeze!