ASP.NET Core in .NET 8 is on The Way! Discover the NEW Features
Tags: csharp, dotnet, aspdotnet, news
Published: 2023-05-22 11:36:14

Yes, you are reading correctly, the latest news about ASP.NET Core has been released! We’re about to dive into all the exciting new features and updates aimed at providing you a more efficient and enjoyable development experience

The ASP.NET Core development team has been working hard on these latest features that have been released in this latest Preview. Blazor enhancements, performance improvements and much more! Get ready to explore the ins and outs of API authoring, Native AOT and all the shiny new metrics at your fingertips!

## Blazor

### Streamlining SSR with Blazor Components

Do you fancy fast-loading server-side Blazor pages? As of [.NET 8](https://www.bytehide.com/blog/dotnet-8/ ".NET 8: What's New? (Features & Release date)"), streaming content updates to client-side is possible with **SSR** (Server-Side Rendering)! With async tasks running in parallel and using placeholders, your pages will load faster than ever. Let’s find out how!

This is the new line of code you should add to your Blazor project:

```csharp
// Add this script tag to your Blazor Server project (wwwroot/index.html or wwwroot/_Host.cshtml)
// This script is needed to enable the new Blazor Server-Side Rendering (SSR) feature in .NET 8
// The 'suppress-error' attribute is used to ignore the specified build warning (BL9992) related to loading the script
<script src="_framework/blazor.web.js" suppress-error="BL9992"></script>
```

After that:

```csharp
// Define page routing
@page "/fetchdata"

// Import required namespaces for the Blazor Server project
@using BlazorSSR.Data
@inject WeatherForecastService ForecastService

// Enable server-side rendering for this Blazor component using the StreamRendering attribute
@attribute [StreamRendering(true)]

<PageTitle>Weather forecast</PageTitle>

<h1>Weather forecast</h1>

// Using conditional rendering to display the "Loading..." message while data is being fetched
@if (forecasts is null)
{
    <p><em>Loading...</em></p>
}
else
{
    // Render weather forecasts when the data is available
}

@code {
    private string message;

    // Override the OnInitializedAsync method to fetch weather forecast data asynchronously
    protected override async Task OnInitializedAsync()
    {
        forecasts = await ForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
    }
}
```

In this way the process that follows is that while the asynchronous tasks are running, “Loading…” will be displayed. When they complete their execution, the information will be passed to the client inside the DOM.

### Mastering Form Posts in Blazor SSR

Exciting news! Now it will be easier to deal with form posts when it comes to SSR. Here’s how to start:

Create a model binding context with the `CascadingModelBinder` component in your main layout:

```csharp
// Add this CascadingModelBinder component to your main layout (usually MainLayout.razor)
// The CascadingModelBinder component is used to seamlessly deal with form posts in Blazor SSR (.NET 8)
<CascadingModelBinder>
    @Body
</CascadingModelBinder>
```

Define a form in Blazor using the `EditForm` component and always remember to set the method attribute for form submission handling:

```csharp
// Define a form using the EditForm component, and ensure to set the method attribute for correct form submission handling
@inject FormDataProvider FormData

<EditForm method="POST" Model="exampleModel" OnValidSubmit="HandleSubmit">
    // Bind the Name property of the exampleModel object to the input field
    <InputText @bind-Value="exampleModel.Name" />
    // Add a submit button to trigger form submission
    <button type="submit">Submit</button>
</EditForm>

@code {
    // Instantiate an ExampleModel object
    ExampleModel exampleModel = new();

    protected override void OnInitialized()
    {
        // Manually model bind the form data using the FormDataProvider service
        if (FormData.Entries.TryGetValue("Name", out var nameValues))
        {
            exampleModel.Name = nameValues.First();
        }
    }

    void HandleSubmit()
    {
        // Handle the submitted form data
    }

    // Create a model class with the required properties (e.g., Name)
    public class ExampleModel
    {
        public string? Name { get; set; }
    }
}
```

Although model binding and validation features are yet to be introduced, this is still a fantastic improvement for Blazor users!

### Named Element Routing in Blazor

Now, Blazor has released an extraordinary feature that allows client-side routing to specific HTML elements using URL fragments. No more endless scrolling or getting lost in your app – all thanks to URL fragment magic!

1.  Just add an `id` attribute to your desired element
2.  Blazor automatically scrolls to the element when the URL fragment matches its identifier

If you are wondering why use Named Element Routing in Blazor? Well, here’s a couple of compelling reasons:

-   Effortlessly guide users to what matters most in your app, without them manually scrolling a mile
-   Improve user experience with enhanced navigation capabilities
-   Boost the overall usability and perception of your app

### Bye-Bye .dll Woes: Webcil Packaging for Blazor WebAssembly Apps

Are you tired of dealing with blocked .dll file downloads or .dll usage issues? Webcil packaging is here to save the day! [Webcil](https://github.com/dotnet/runtime/blob/main/docs/design/mono/webcil.md) removes native Windows execution content from .NET assemblies, putting an end to these frustrations.

Start by adding the `WasmEnableWebcil` property to your project file:

```csharp
// Add the WasmEnableWebcil property to your Blazor WebAssembly project file (e.g., .csproj)
// This property enables the Webcil packaging feature, which eliminates issues related to blocked .dll file downloads
<PropertyGroup>
    <WasmEnableWebcil>true</WasmEnableWebcil>
</PropertyGroup>
```

### Minimal APIs Now Support Form Binding

If you’re a fan of minimal APIs, you’ll be thrilled to hear that form binding for specific types is now possible without the assistance of the `FromForm` attribute. This update applies to `IFormCollection`, `IFormFile` and `IFormFileCollection`.

Here you can see the [Microsoft example](https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-preview-4/):

```csharp
// Create a minimal API WebApplication instance
var app = WebApplication.Create();

// Function to generate or retrieve a file path for the uploaded file
string GetOrCreateFilePath(string fileName, string filesDirectory = "uploadFiles")
{
    var directoryPath = Path.Combine(app.Environment.ContentRootPath, filesDirectory);
    Directory.CreateDirectory(directoryPath);
    return Path.Combine(directoryPath, fileName);
}

// Function to upload the file with the specified name
async Task UploadFileWithName(IFormFile file, string fileSaveName)
{
    var filePath = GetOrCreateFilePath(fileSaveName);
    await using var fileStream = new FileStream(filePath, FileMode.Create);
    await file.CopyToAsync(fileStream);
}

// Use the MapPost method to define a POST route that accepts an IFormFile parameter without needing the FromForm attribute
app.MapPost("/upload", async (IFormFile file) => {
    var fileSaveName = Guid.NewGuid().ToString("N") + Path.GetExtension(file.FileName);
    await UploadFileWithName(file, fileSaveName);
    return TypedResults.Ok("File uploaded successfully!");
});

// Start and run the WebApplication
app.Run();
```

Remember to protect your apps against [XSRF attacks](https://learn.microsoft.com/aspnet/core/security/anti-request-forgery?view=aspnetcore-7.0). This [code sample](https://gist.github.com/captainsafia/6b1f57026af53ae73bb5a2e58a68c4b8) will show you how to enable anti-forgery services in ASP.NET minimal APIs.

### Boost Your API Development with `.http` Files

New API projects now come with an included `.http` file:

```csharp
// The .http file simplifies testing your app's endpoints using the new Visual Studio HTTP editor
// Define your API host address to avoid hardcoding it in each request
@MyApi_HostAddress = http://localhost:5233

// Test a GET request to fetch all todos by using the defined API host address
GET {{MyApi_HostAddress}}/todos/
Accept: application/json

// Use the three hash (#) symbols to separate different request examples

// Test another GET request to fetch a specific todo item (e.g., with id 1)
GET {{MyApi_HostAddress}}/todos/1
Accept: application/json

// Add more request examples with different HTTP methods and endpoints as needed
```

Get ready to make the most of this supercharged API development experience!

## Native AOT

### Streamlined Logging and Exception Handling in Compile-time Minimal APIs

Did you know that you can now bring automatic logging and [exception handling](https://www.bytehide.com/blog/5-good-practices-for-error-handling-in-c/ "Mastering C# Exception Handling: Techniques and Best Practices") to your compile-time minimals APIs through the [Request Delegate Generator](https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-preview-3/#minimal-apis-and-native-aot)? Microsoft sure knows how to cater to developers!

![a](https://www.bytehide.com/blog/wp-content/uploads/2023/05/image-6-550x294.png)

Take a look at these API endpoints activated by `<EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator>`:

```csharp
// Create a minimal API WebApplication instance
var app = WebApplication.Create();

// Define an API endpoint activated by enabling the Request Delegate Generator (RDG)
// Automatic logging and exception handling are provided by RDG, simplifying development
app.MapGet("/hello/{name}", (string name)
    => $"Hello {name}!");

// Define another API endpoint that calculates age based on the input birthdate
app.MapGet("/age", (DateTime birthDate)
    => $"You're about {DateTime.Now.Year - birthDate.Year} years old!");

// Start and run the WebApplication
app.Run();
```

In this example, in the case that you send any request but you do not provide the `name` parameter to `/hello`, you’ll experience a `BadHttpRequestException`:

```csharp
// Send a request without providing the required 'name' parameter in the /hello endpoint
// The following cURL command will cause a BadHttpRequestException, as the parameter is not specified:
curl "http://localhost:5056/hello"

// The exception message will look like this:
/*
Microsoft.AspNetCore.Http.BadHttpRequestException: Required parameter "string name" was not provided from route or query string.
   ....
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
*/
```

The same applies here, an unparsable `birthDate` parameter in the `/age` endpoint will prompt another exception:

```csharp
// Send a request with an unparsable 'birthDate' parameter in the /age endpoint
// The following cURL command will cause a BadHttpRequestException due to the 'invalidDate' value:
curl "http://localhost:5056/age?birthDate=invalidDate"

// The exception message will look like this:
/*
Microsoft.AspNetCore.Http.BadHttpRequestException: Failed to bind parameter "DateTime birthDate" from "invalidDate".
   ...
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
*/
```

## ASP.NET Core Metrics

The latest release brings new ASP.NET Core metrics, thanks to the awesomeness of [System.Diagnostics.Metrics](https://learn.microsoft.com/dotnet/core/diagnostics/compare-metric-apis#systemdiagnosticsmetrics). Huh, isn’t that cool?

Now, you might be wondering, “sure, that sounds great, but what’s in it for me?” Hold on to your hats because these new metrics are a game-changer, especially compared to those old-timer event counters. Here’s a taste of what’s on offer with Metrics:

### New Measurement Types

Get ready for a whole new level of measurement goodness! Say hello to counters, gauges, and histograms. Imagine all the possibilities with these new tools at your disposal!

### Enhanced Multi-Dimensional Value Reporting

Who doesn’t love adding a little extra dimension to their life? With enhanced multi-dimensional value reporting, you’ll dive deeper into understanding your application’s performance. It’s like having X-ray vision into your app, but you know… without any side effects.

### Compatibility with Cloud-Native Ecosystems

Raise your hand if you love OpenTelemetry! This impressive addition ensures that your ASP.NET Core metrics play nicely with your favorite cloud-native ecosystem. Finally, no more awkward silos and barriers, just pure harmony!

So, fellow C# enthusiasts, are you excited yet to dive into these shiny new ASP.NET Core metrics? I know I am! These new features are not just mind-blowing, but also insanely practical for optimizing our applications. Don’t let your app’s performance leave you guessing – embrace the Metrics revolution and optimize your way to success!

## Conclusion

As we wrap up this overview of ASP.NET Core .NET 8 Preview 4’s new features and updates, you can now see how it’s poised to transform the way you build and monitor web applications, all while ensuring a smooth and pleasant development experience.

With the enhancements to Blazor, minimal APIs, Native AOT and newly introduced metrics, you can be confident that you’ll have everything you need to create performant and scalable applications with ease. Don’t hesitate to explore these features even further and integrate them into your projects today. Surf’s up! Ride the wave of exciting new possibilities ASP.NET Core .NET 8 Preview 4 has in store for you!