dotnet watch Razor files in ASP.NET Core 3

Prior to .NET Core 3 Razor (cshtml) files were compiled during runtime by default. This did result in in a Views folder which had to be published and gave you the possibility to alter your views without recompiling your web application.

Starting with ASP.NET Core 3 the default has been switched to build-time compilation which gives you an additional dll containing the compiled Razor views:


If you want to use the .NET watcher process to automatically rebuild your app on code changes with dotnet watch you will notice that it can get pretty annoying when working with your views.
Your views will now also trigger a code change as they need to be compiled too, which will make your coding/debugging experience stand still for a few seconds (depending on your project size and PC specs).

The solution is to use runtime compilation for coding/debugging and build-time compilation for production, so we still get all the benefits of pre-compiled views in our production apps.

I've found a CommandLineOptions.cs file in the ASP.NET Core repository which gives us this nice overview of environment variables used when running the watcher:


But first we will have to opt-in to runtime compilation by installing the Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation NuGet package.

By querying the DOTNET_WATCH environment variable in our Startup.cs we can decide which compilation method we want to use for our views.

For MVC add this to the ConfigureServices(...) method:

IMvcBuilder mvc = services.AddControllersWithViews();
if (Environment.GetEnvironmentVariable("DOTNET_WATCH") == "1")

For Razor pages you have to replace AddControllersWithViews() with AddRazorPages().

The AddRazorRuntimeCompilation() extension method is part of the afore-mentioned NuGet package and is located in the namespace Microsoft.Extensions.DependencyInjection.

That's it. Now your app won't rebuild anymore when changing .cshtml files while using dotnet watch run.