Hot Module Replacement (HMR) for ASP.NET Core in .NET 9

Tapesh Mehta Tapesh Mehta | Published on: Feb 16, 2026 | Est. reading time: 10 minutes
Hot Module Replacement (HMR) for ASP.NET Core in .NET 9

Modern web development demands rapid iteration cycles, and few features accelerate development velocity like Hot Module Replacement (HMR). With .NET 9, ASP.NET Core has significantly enhanced HMR capabilities, enabling developers to see code changes reflected in their browsers without losing application state or waiting for full rebuilds. This advancement transforms the development experience for ASP.NET Core applications, bringing productivity gains previously exclusive to frontend-focused frameworks.

Hot Module Replacement automatically updates your running application when you modify source files, preserving application state and maintaining your position in the user interface. Unlike traditional hot reload that refreshes the entire page, HMR intelligently patches only the changed modules, making it invaluable for complex debugging scenarios and UI refinement work.

Table of Contents

Understanding Hot Module Replacement in ASP.NET Core

Hot Module Replacement in .NET 9 builds upon the foundation of .NET Hot Reload but extends it specifically for web applications. While Hot Reload focuses on applying code changes without restarting the debugger, HMR goes further by updating the browser runtime without page refreshes. This distinction is crucial for maintaining complex application state during development.

The HMR system works through a WebSocket connection between your development server and the browser. When you modify a file, the .NET build system detects the change, compiles only the affected modules, and pushes updates through the WebSocket. The browser runtime then applies these changes without disrupting your application’s current state, similar to how Native AOT compilation in .NET 9 optimizes deployment without sacrificing development experience.

Key Benefits of Hot Module Replacement

The primary advantage of HMR is dramatically reduced feedback loops during development. Traditional development cycles require saving files, waiting for builds, refreshing browsers, and navigating back to the same application state. HMR eliminates most of these steps, allowing you to see changes within milliseconds while maintaining your current debugging context.

State preservation is particularly valuable when working on specific UI components deep within an application flow. Without HMR, testing a change to a checkout confirmation dialog might require clicking through multiple screens after each modification. With HMR, the dialog remains open and updates instantly as you refine the code.

Configuring Hot Module Replacement in .NET 9

Enabling HMR in your ASP.NET Core project requires minimal configuration. The feature integrates with the standard development server and works with both Razor Pages and Blazor applications. For optimal results with Angular development or React development alongside ASP.NET Core, additional configuration ensures frontend and backend changes sync seamlessly.

Basic Setup for Razor Pages

For Razor Pages applications, HMR works out of the box in .NET 9 when running in development mode. The following Program.cs configuration ensures HMR is properly enabled:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container
builder.Services.AddRazorPages();

if (builder.Environment.IsDevelopment())
{
    builder.Services.AddRazorPages()
        .AddRazorRuntimeCompilation();
}

var app = builder.Build();

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

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();

app.Run();

The AddRazorRuntimeCompilation method is essential for HMR to function with Razor views. This enables the runtime to recompile views when changes are detected, which the HMR system then pushes to the browser.

Advanced Configuration for Blazor Server

Blazor Server applications benefit most from HMR due to their stateful nature. Configure your Blazor app for optimal HMR performance:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

if (builder.Environment.IsDevelopment())
{
    builder.Services.Configure<RazorPagesOptions>(options =>
    {
        options.RootDirectory = "/Components";
    });
}

var app = builder.Build();

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

app.UseStaticFiles();
app.UseAntiforgery();

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

This configuration ensures Blazor components update through HMR while maintaining SignalR connections that power Blazor Server’s interactivity, similar to how health checks in ASP.NET Core maintain system reliability through continuous monitoring.

Hot Module Replacement for Static Assets

Static assets like CSS, JavaScript, and images also support HMR in .NET 9. The development server monitors these files and updates them in the browser without page refreshes. This is particularly powerful when fine-tuning styles or debugging client-side JavaScript.

CSS and JavaScript HMR

For CSS files, HMR injects updated stylesheets without reloading the page. This means you can adjust colors, spacing, or layouts and see changes instantly while maintaining scroll position and form state. JavaScript modules also reload automatically when using ES6 module syntax:

// app.js - This module will hot reload
export class AppModule {
    constructor() {
        this.initializeComponents();
    }

    initializeComponents() {
        // Component initialization logic
        console.log('App components initialized');
    }

    updateTheme(theme) {
        document.body.className = theme;
    }
}

// Enable HMR for this module
if (module.hot) {
    module.hot.accept('./app.js', function() {
        console.log('Module updated via HMR');
        // Optionally preserve state during updates
    });
}

The module.hot API allows you to control how updates are applied. You can preserve state, clean up resources, or trigger specific update logic when modules reload. This level of control is invaluable for maintaining complex client-side state during development.

Integrating HMR with Frontend Frameworks

When building modern web applications, you often combine ASP.NET Core with frontend frameworks like Angular or React. .NET 9’s HMR works alongside these frameworks’ own hot reload systems, creating a unified development experience. For comprehensive web development projects, this integration is essential.

Angular Integration

For Angular applications, configure the ASP.NET Core SPA proxy to work with Angular CLI’s development server:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSpa(spa =>
    {
        spa.Options.SourcePath = "ClientApp";
        spa.UseAngularCliServer(npmScript: "start");
    });
}
else
{
    app.UseSpaStaticFiles();
    app.UseSpa(spa =>
    {
        spa.Options.SourcePath = "ClientApp";
    });
}

app.UseRouting();
app.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action=Index}/{id?}");

app.Run();

This configuration allows Angular’s HMR to work independently while ASP.NET Core HMR handles server-side changes. Both systems coexist, providing seamless updates whether you modify TypeScript components or C# controllers.

React Integration

React applications using Vite or Create React App have similar integration patterns. The key is configuring the proxy to forward API requests while allowing the frontend dev server to handle HMR:

{
  "name": "client-app",
  "version": "0.1.0",
  "private": true,
  "proxy": "https://localhost:5001",
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build"
  }
}

The proxy setting ensures API calls route to your ASP.NET Core backend while React’s development server handles all frontend assets with its own HMR implementation. This creates a cohesive development environment where changes to either frontend or backend components update automatically.

Troubleshooting Hot Module Replacement Issues

While HMR significantly improves development workflows, certain scenarios can prevent it from working correctly. Understanding common issues and their solutions ensures you maintain productivity when problems arise.

WebSocket Connection Failures

HMR relies on WebSocket connections between the browser and development server. Corporate proxies, firewalls, or incorrect HTTPS configurations can block these connections. Verify WebSocket connectivity by checking the browser’s developer console for connection errors:

var builder = WebApplication.CreateBuilder(args);

if (builder.Environment.IsDevelopment())
{
    builder.WebHost.ConfigureKestrel(options =>
    {
        options.ListenLocalhost(5000);
        options.ListenLocalhost(5001, listenOptions =>
        {
            listenOptions.UseHttps();
        });
    });
}

var app = builder.Build();

// Enable WebSocket support
app.UseWebSockets(new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromSeconds(120)
});

app.Run();

Explicitly enabling WebSockets with appropriate keep-alive settings ensures stable HMR connections. The keep-alive interval prevents idle connections from being terminated by network infrastructure, maintaining the real-time update channel.

Build Cache Issues

Occasionally, build caches can become corrupted, causing HMR to apply outdated changes or fail entirely. Cleaning the build cache often resolves these issues:

# Clean all build artifacts
dotnet clean

# Remove bin and obj directories
rm -rf bin obj

# Restore packages
dotnet restore

# Rebuild project
dotnet build

For persistent issues, clearing the NuGet cache can help. In Visual Studio, this is accessible through Tools → NuGet Package Manager → Package Manager Settings → Clear All NuGet Cache(s). This nuclear option should resolve most cache-related HMR problems.

Performance Optimization for Hot Module Replacement

While HMR is fast by design, large projects can experience slower update times. Several optimization strategies can maintain rapid feedback loops even as your codebase grows, complementing the performance gains from features like those described in ASP.NET Core performance best practices.

Selective File Watching

By default, the development server watches all project files. In large solutions with many projects or generated files, this can overwhelm the file watcher. Configure selective watching to monitor only relevant directories:

{
  "dotnet-watch": {
    "exclude": [
      "**/bin/**",
      "**/obj/**",
      "**/node_modules/**",
      "**/*.generated.cs",
      "**/wwwroot/lib/**"
    ],
    "include": [
      "**/*.cs",
      "**/*.cshtml",
      "**/*.razor",
      "wwwroot/css/**/*.css",
      "wwwroot/js/**/*.js"
    ]
  }
}

Add this configuration to your project file or create a separate dotnet-watch.json file. Excluding generated files, package directories, and build artifacts significantly reduces file system overhead while maintaining HMR functionality for source files.

Incremental Build Configuration

Enable incremental builds to minimize compilation time for HMR updates. This is especially valuable for projects utilizing enterprise-scale .NET solutions where build times can become significant:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    
    <!-- Optimize for development -->
    <UseAppHost>false</UseAppHost>
    <ServerGarbageCollection>false</ServerGarbageCollection>
    
    <!-- Enable incremental builds -->
    <IncrementalBuild>true</IncrementalBuild>
    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
  </PropertyGroup>
  
  <PropertyGroup Condition="'$(Configuration)' == 'Debug'">
    <Optimize>false</Optimize>
    <DebugType>portable</DebugType>
  </PropertyGroup>
</Project>

These project settings prioritize fast iteration during development. Disabling AppHost and server garbage collection reduces startup time, while incremental builds ensure only modified code paths recompile. In production configurations, these optimizations should be reversed for maximum runtime performance.

Best Practices for Hot Module Replacement Development

Maximizing HMR effectiveness requires adapting your development workflow to leverage its capabilities. These practices ensure you get the most value from the feature while avoiding common pitfalls.

First, structure your application with HMR in mind. Keep components small and focused, as granular modules reload faster and more reliably than large, monolithic files. This aligns with general software engineering best practices while providing tangible HMR performance benefits.

Second, use dependency injection effectively. HMR works best when components can be replaced independently. Tight coupling between modules can prevent clean updates, forcing full page reloads. Design your services and components to be modular and replaceable, just as you would when implementing event-driven architecture with .NET.

Third, be mindful of state management. HMR preserves application state, which is usually beneficial but can occasionally mask bugs that only appear on fresh page loads. Periodically test with full refreshes to ensure your application initializes correctly from scratch.

Conclusion

Hot Module Replacement in .NET 9 represents a significant advancement in ASP.NET Core development tooling. By eliminating the traditional edit-compile-refresh cycle, HMR enables developers to maintain focus and flow state while building web applications. The feature works seamlessly with Razor Pages, Blazor, and modern frontend frameworks, creating a unified development experience regardless of your technology stack.

Implementing HMR requires minimal configuration but delivers substantial productivity gains. From instant CSS updates to stateful component reloading, the feature accelerates every aspect of web development. Combined with .NET 9’s other improvements to build performance and runtime efficiency, HMR helps development teams deliver high-quality applications faster than ever before.

Whether you’re building enterprise applications or rapid prototypes, investing time to properly configure and optimize HMR pays dividends throughout your project lifecycle. The faster feedback loops enable more experimentation, better designs, and ultimately superior user experiences. As web development continues evolving toward more interactive and stateful applications, HMR ensures .NET remains a compelling choice for modern development teams.

Share

clutch profile designrush wirefuture profile goodfirms wirefuture profile
Join the Digital Revolution with WireFuture! 🌟

Step into the future with WireFuture at your side. Our developers harness the latest technologies to deliver solutions that are agile, robust, and ready to make an impact in the digital world.

Hire Now

Categories
.NET Development Angular Development JavaScript Development KnockoutJS Development NodeJS Development PHP Development Python Development React Development Software Development SQL Server Development VueJS Development All
About Author
wirefuture - founder

Tapesh Mehta

verified Verified
Expert in Software Development

Tapesh Mehta is a seasoned tech worker who has been making apps for the web, mobile devices, and desktop for over 15+ years. Tapesh knows a lot of different computer languages and frameworks. For robust web solutions, he is an expert in Asp.Net, PHP, and Python. He is also very good at making hybrid mobile apps, which use Ionic, Xamarin, and Flutter to make cross-platform user experiences that work well together. In addition, Tapesh has a lot of experience making complex desktop apps with WPF, which shows how flexible and creative he is when it comes to making software. His work is marked by a constant desire to learn and change.

Get in Touch
Your Ideas, Our Strategy – Let's Connect.

No commitment required. Whether you’re a charity, business, start-up or you just have an idea – we’re happy to talk through your project.

Embrace a worry-free experience as we proactively update, secure, and optimize your software, enabling you to focus on what matters most – driving innovation and achieving your business goals.

Hire Your A-Team Here to Unlock Potential & Drive Results
You can send an email to contact@wirefuture.com
clutch wirefuture profile designrush wirefuture profile goodfirms wirefuture profile good firms award-4 award-5 award-6