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, 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:
// 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:
// 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:
// 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:
// 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!
- Just add an
id
attribute to your desired element - 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 removes native Windows execution content from .NET assemblies, putting an end to these frustrations.
Start by adding the WasmEnableWebcil
property to your project file:
// 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:
// 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. This code sample 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:
// 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 to your compile-time minimals APIs through the Request Delegate Generator? Microsoft sure knows how to cater to developers!
Take a look at these API endpoints activated by <EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator>
:
// 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
:
// 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:
// 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. 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!
Top comments (5)
Those
.http
files look like they'll come in handy.As always, thanks for the summary of what's new!
They are not handy at all, the opposite. They encourage you to NOT write unit test, but debug/test your application manually by executing these commands.
Set up unit test infrastructure once and have your tests written, save your time, help your colleagues, do CI.
Ah - I didn't realise that. I thought they were an alternative way to write other types of tests.
Still, unit tests can be very difficult to write for controller endpoints (as things like HTTP context will be
null
in unit tests), and one or two manual tests are still needed even when you have the rest of your test infrastructure set up. It looks like it could be an alternative to making requests during development with Postman, which is still handy.To be clear, I'm not suggesting to do manual testing instead of automated testing; but in addition to it.
Google for
WebApplicationFactory
and you will get your SUT as it was deployed in production, with HTTP Context, ectThanks for the pointer!