.NET Tools
Essential productivity kit for .NET and game developers
JetBrains Rider .NET Watch Run Configuration Plugin
Most modern technology stacks now include a quick feedback loop mechanism. These mechanisms allow you to change your codebase and avoid the tedious tasks of stopping and restarting the existing application session. You may typically refer to this as hot reload or live reload. In the .NET world, “hot reload” is additional functionality integrated into the dotnet watch tool.
This post will explore the subtle differences between running dotnet watch
with and without hot reload and when you might prefer running in either mode. We’ll also look at a JetBrains Rider run configuration that allows you to get a more hands-off experience than the one built into the IDE.
Note: The .NET Watch Run Configuration is bundled with Rider 2024.2 and newer. Give it a try!
What is dotnet watch?
Dotnet watch
is a CLI tool that ships with current versions of the .NET SDK. You can run any .NET application using dotnet watch
as its primary purpose is to, unsurprisingly, watch for changes in files related to your solution. In a running .NET project, the dotnet watch process will look for changes in *.cs
, *.csproj
, *.resx
files, and any changes found in a web apps wwwroot
folder. While there are certain defaults, you can configure dotnet watch to recognize any file located in a project with a few changes in your .csproj
file. Any detected change will attempt a hot reload, or if that is not possible, a process restart will occur.
Generally, dotnet watch is helpful in several development scenarios:
- Continuous unit test runs
- Web design changes to Web-based files like HTML, CSS, and JavaScript.
- When creating Read-eval-print loop (REPL) experiences
If you want to edit a file and have the app restart, dotnet watch
is what you want. However, it isn’t all rainbows and unicorns. The CLI tool has some drawbacks. For example, you may inadvertently change a file, causing you to lose state in your application session. Luckily for you, .NET 6 introduced hot reload.
What is .NET’s Hot Reload?
Hot reload is a functionality of dotnet watch that allows you to make code changes without restarting your application. The goal is to preserve your current state to experiment with changes more quickly than you previously could, eliminating the lost time to a restart.
Making code edits to method bodies will allow you to swap newly updated functionality, replacing the previous implementation. However, like most things, there are limitations to hot reloading:
- Changing parameters to methods breaks contracts, requiring a restart
- Configuration code that’s run once typically requires a restart
- Changes outside of method bodies are not supported
- New
await
oryield
operators change code flow and are not supported - Refactoring method names is not supported
These might not seem like significant issues, but in an increasingly async
world, you’ll find yourself in these scenarios more than you like. Developers refer to these changes as “rude edits”. Rude edits typically give you two options: continue using the application state as it currently stands or restart your app to see your latest changes.
Both modes are potent options for .NET developers, but considering how you want your development experience to feel will determine whether you choose to run dotnet watch
with or without hot reload.
Dotnet watch Run Configuration plugin
While JetBrains Rider has support for hot reload built into the development experience, it may not be the ideal development experience for some developers. For developers willing to accept an application restart for a more comprehensive list of code change options, dotnet watch
with hot reload disabled might be a better option.
Luckily, you can install a .NET Watch Run Configuration plugin that adds a new run configuration to JetBrains Rider. The plugin adds a new run configuration that allows you to set several options before invoking the CLI tooling.
- Project Selection from the current solution
- Set the Target Framework (if there are multiple target frameworks)
- Add additional Program Arguments
- Set Environment Variables
- Set
dotnet watch
verbosity:--quiet
,--verbose
, or default - Suppress Hot reload
- Always restart on rude edit (6.0.2+ only)
- Before launch options
Like all run configurations, you can also save these configurations as project files to share with team members. Also, create as many run configurations as you’d like, but be aware of assembly contention.
The advantage to the plug-in is it’s hands-off, just like running the command from a terminal window. You can continue to edit your app, and the process will attempt to use hot reload, or if you’ve added an environment variable DOTNET_WATCH_RESTART_ON_RUDE_EDIT
to “true"
, the process will restart without a prompt. Note that the environment variable is only available for .NET 6.0.2+. You can also check this property in a specific run configuration to not affect your entire development environment.
One limitation to using dotnet watch
is that the process identifier changes upon each restart. The changing process means it is not currently possible to attach the debugger to the process and continue to make code edits.
As mentioned in the previous section, you must be mindful of the application you are creating and whether it makes sense to have hot reload enabled or disabled.
For example, ASP.NET Core Minimal API applications rely heavily upon lambda expressions, one-time registration of endpoints, and configuration of the ASP.NET Core pipeline. This application might benefit from having hot reload disabled and forcing the process to restart.
The good news is these run configurations can be modified and duplicated at any time, giving you and your team members flexibility in your development workflow.
Conclusion
Dotnet watch
is a fantastic addition to the .NET technology stack, and with multiple operating modes, you can configure your development workflow to meet your specific needs.
The current hot reload experience in JetBrains Rider is excellent for methodically applying changes when and where you want. Still, adding the dotnet watch run configuration plugin gives folks more workflow options, and more options are always great, right? Of course!
If you’d like to try the dotnet watch run configuration plugin, you can install it via the JetBrains Marketplace or search for it in your JetBrains Rider settings. If you have any feedback, please leave it in the comments below.