What's New for ASP.NET Core & Blazor in .NET 9

Posted by: Suprotim Agarwal , on 11/15/2024, in Category ASP.NET Core
Views: 10236
Abstract: .NET 9 is here, and it's packed with goodies for ASP.NET Core and Blazor! Let's explore the cool new features like smarter static assets, smoother Blazor, and easier authentication.

.NET 9 has just landed, and it’s bringing some seriously cool updates to ASP.NET Core and Blazor. Think faster apps, simpler coding, and slicker experiences for everyone – both on the server and the client side.

In this article, we’re going to take an in-depth look at two of the biggest improvements in .NET 9.

We’ll explore how ASP.NET Core is now super smart about delivering static files, and we’ll dive into the fresh, awesome features in Blazor. Whether you’re building big web apps or playing in the hybrid native/web space, these updates are designed to make your life easier and your apps shine.

Get ready to develop quicker, create leaner code, and build applications that are just plain more robust!

Here’s what we’re going to unpack:

  • Smarter Static Asset Delivery in ASP.NET Core – get ready for speed!
  • Blazor’s Interactive Experience – it just got a whole lot smoother.
  • Authentication State Serialization – finally, it’s simplified!

1. Making Static Files Lightning Fast with MapStaticAssets

Let’s talk performance!

One of the most impactful enhancements in ASP.NET Core for .NET 9 is the introduction of the MapStaticAssets middleware.

If you’re familiar with ASP.NET Core, you’ve likely used UseStaticFiles() to serve static content like CSS, JavaScript, and images. MapStaticAssets() is the evolution of this, taking static file delivery to the next level.

Instead of simply serving files, MapStaticAssets() intelligently optimizes the process during build and publish time.

It streamlines how static files are delivered, working seamlessly with UI frameworks like Blazor, Razor Pages, and MVC. For most scenarios, especially with assets known at build time, MapStaticAssets can effectively replace UseStaticFiles.

Benefits of Optimized Static Asset Delivery

Why is optimized static file delivery important?

It boils down to creating faster, more efficient web applications that provide a better user experience and can even improve your site’s SEO ranking.

Here’s how MapStaticAssets() delivers these benefits:

Automatic Compression:

MapStaticAssets pre-compresses your assets using gzip in development and both gzip and brotli in published applications.

Compression drastically reduces file sizes (potentially by up to 90% for some libraries). This leads to:

Faster Page Load Times: Browsers download smaller files much quicker, making your website feel snappier.

Reduced Bandwidth Usage: Lower bandwidth consumption, which is especially beneficial for users on limited data plans and for reducing server costs.

aspnetcore9-mapstaticassets-optimization

Figure: Flowchart illustrating the automatic compression process in MapStaticAssets, showing input assets and compressed output assets for development and production.

Smart ETags (Entity Tags):

MapStaticAssets generates content-based ETags by creating SHA-256 hashes of file content.

ETags act as unique fingerprints for file versions. Browsers use ETags to efficiently check if a file has changed since the last visit. If the ETag matches, the browser uses its cached version, avoiding unnecessary downloads.

This results in:

  • Efficient Browser Caching: Reduces redundant data transfer, making repeat visits to your site much faster.
  • Lower Server Load: Less server processing and bandwidth are needed to serve unchanged static files.
  • Filename Fingerprinting (Cache-Busting): This technique automatically appends unique fingerprints (hashes) to filenames (e.g., app.abc123.css). Filename fingerprinting is a powerful cache-busting strategy. It ensures that when you deploy updates, users always get the newest versions of your static assets. This eliminates cache-related issues where users might see outdated website versions after deployments.
  • Guaranteed Latest Assets for Users: Users always see the most up-to-date website content after deployments.
  • No More Troubleshooting Outdated Cache Issues: Reduces user frustration and support queries related to outdated cached files.

How to Use MapStaticAssets – Implementation

To take advantage of MapStaticAssets, simply replace the UseStaticFiles() middleware call in your Program.cs file with MapStaticAssets().

Basic usage typically requires no extra configuration.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseRouting();

// Simply replace UseStaticFiles with MapStaticAssets for optimized static asset delivery. Basic scenarios need no extra configuration.
app.MapStaticAssets();
// (Note that if you were using UseStaticFiles() for default static file serving, you can now remove it)

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

Understanding the Code Example 

var builder = WebApplication.CreateBuilder(args)

This line sets up the web application builder, which is essential for configuring services and middleware. 

app.MapStaticAssets()

This single line is where the optimization is enabled. It replaces app.UseStaticFiles() and activates the enhanced static asset delivery. No further configuration is needed for typical use cases, making it a straightforward performance boost. 

app.MapBlazorHub(); and app.MapFallbackToPage("/_Host")

These lines are standard Blazor setup, mapping Blazor Hub and fallback routing, and are unaffected by the MapStaticAssets middleware.

After implementing this change, your static files will be served with build-time compression, content-based ETags, and filename fingerprinting.

To verify, inspect your browser’s developer tools and examine the HTML – you’ll see unique fingerprints in the filenames of your static assets (e.g., app.fingerprint123.css).  

2. Blazor Gets Even More Interactive and Hybrid-Friendly

Let’s shift focus to Blazor. .NET 9 significantly enhances Blazor, making it even more powerful for building interactive web experiences.

Key improvements include advancements in hybrid app development, smarter render mode detection, and streamlined dependency injection.

Blazor Hybrid and Enhanced Server Reconnection

The .NET MAUI Blazor Hybrid template in .NET 9 empowers developers to create applications that share a common UI core across web and native platforms.

Using a single Razor Class Library (RCL), you can build UI components that function seamlessly in both native MAUI apps and standard Blazor web apps. This maximizes code reuse, saving development time and ensuring UI consistency across platforms.

For example, a logistics company could leverage a single Blazor Hybrid app to operate on tablets (as a native MAUI application for field operations) and simultaneously as a web dashboard (for office-based fleet management). This demonstrates the versatility and code efficiency gains of Blazor Hybrid.

blazor-hybrid-architecture

Figure: Diagram illustrating the Blazor Hybrid architecture, showing a single Razor Class Library powering both a .NET MAUI native app and a Blazor Web App.

Furthermore, Blazor Server in .NET 9 features significantly improved server reconnection logic.

In production environments, network hiccups or temporary disconnections are realities. Blazor’s enhanced reconnection mechanism now provides a more resilient user experience. If a SignalR connection is interrupted, Blazor now attempts to:

  • Immediate Reconnection: Try to re-establish the connection instantly.
  • Exponential Backoff: If the immediate reconnection fails, it intelligently uses an exponential backoff strategy. This means reconnection attempts start frequently and then become less frequent, reducing server load while still actively trying to reconnect.
  • Navigation-Based Reconnection: When a user navigates back to a Blazor application after a disconnection, reconnection attempts are triggered immediately, ensuring a faster return to an interactive state.

These reconnection enhancements minimize user disruption and reduce the need for disruptive full-page refreshes, leading to more robust and user-friendly Blazor Server applications in real-world deployment scenarios.

Context-Aware Components and Constructor Injection

.NET 9 introduces the RendererInfo API, giving Blazor components runtime awareness of their rendering environment. Components can now use properties like RendererInfo.Name and ComponentBase.AssignedRenderMode to determine their current render mode (static SSR or interactive WebAssembly/server-side).

This allows for conditional UI rendering based on the environment. A practical example is displaying a loading indicator only during the transition to interactive rendering, thus providing users with better feedback and a smoother initial experience.

Constructor injection in Razor components is another significant improvement in .NET 9.

While the [Inject] attribute remains available, constructor injection offers a cleaner, more structured approach to dependency injection.

By injecting dependencies directly into a component’s constructor, you create more modular, testable, and maintainable code. This is especially beneficial in larger Blazor projects, promoting better code organization and separation of concerns. 

// Example Blazor component demonstrating constructor injection
public partial class CounterComponent : ComponentBase
{
    private readonly NavigationManager _navigation;

    // Constructor injection: NavigationManager instance provided here
    public CounterComponent(NavigationManager navigation)
    {
        _navigation = navigation;
    }

    private void NavigateToCounter() => _navigation.NavigateTo("/counter");

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        // Simple button using the injected NavigationManager
        builder.OpenElement(0, "button");
        builder.AddAttribute(1, "onclick", EventCallback.Factory.Create(this, NavigateToCounter));
        builder.AddContent(2, "Go to Counter");
        builder.CloseElement();
    }
}

Understanding the Code Example: 

private readonly NavigationManager _navigation

Declares a private, read-only field to hold the NavigationManager dependency. readonly ensures that the dependency is set only via the constructor.

public CounterComponent(NavigationManager navigation)

This is the constructor where NavigationManager is injected. Blazor’s dependency injection system automatically provides an instance of NavigationManager when CounterComponent is created.

_navigation = navigation

Assigns the injected NavigationManager instance to the private field, making it available for use within the component’s logic.

private void NavigateToCounter() => _navigation.NavigateTo("/counter")

This method demonstrates using the injected NavigationManager to perform navigation, showcasing how the dependency is utilized within the component’s logic.

Constructor injection, as demonstrated, leads to more explicit dependency declaration and cleaner component design compared to solely relying on [Inject] attributes.

3. Simplified Authentication State Management

Managing authentication state in Blazor Web Apps has been simplified in .NET 9.

The new authentication state serialization APIs reduce the boilerplate previously needed to handle serialization and deserialization between server and client components. This streamlining simplifies project structure and reduces maintenance.

For instance, in a multi-user web dashboard application, efficient retention of login states across client and server components becomes crucial. .NET 9’s simplified authentication state serialization ensures that user sessions are maintained smoothly, minimizing unnecessary authentication roundtrips and enhancing the overall responsiveness and security of the application.

Steps to Configure Authentication State Serialization:

To implement simplified authentication state serialization, follow these steps in your project’s Program.cs files:

  1. Server Project Configuration: Add AddAuthenticationStateSerialization() in your server project’s service registrations.
  2. Client Project Configuration: Configure your client project with AddAuthorizationCore(), AddCascadingAuthenticationState(), and AddAuthenticationStateDeserialization().
  3. (Optional) Claim Customization: Customize claim serialization settings if you need to serialize claims beyond the default name and role claims.

By adding these service extensions, you eliminate the need for the custom code files that were previously required for authentication state management.

This results in cleaner, less complex Blazor projects and reduced long-term maintenance.

Conclusion

.NET 9 delivers a compelling set of enhancements for ASP.NET Core and Blazor developers.

From the performance gains of MapStaticAssets to Blazor’s improved hybrid capabilities, enhanced interactivity, and simplified authentication, these updates collectively contribute to a more efficient and enjoyable development experience.

These improvements empower developers to build modern, scalable, and highly responsive web applications with less boilerplate and improved performance characteristics.

Further Reading:

So, which of these .NET 9 features sparks your interest the most for your next project?

Let’s discuss in the comments below!

Note: This article has been enhanced using AI to reframe sentences for clarity, readability, and engagement while ensuring the content remains accurate and valuable. 

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of DotNetCurry, DNC Magazine for Developers, SQLServerCurry and DevCurry. He has also authored a couple of books 51 Recipes using jQuery with ASP.NET Controls and The Absolutely Awesome jQuery CookBook.

Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.

Get in touch with him on Twitter @suprotimagarwal or at LinkedIn



Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!