Imagine this scenario: you're weeks into building a new website in Umbrco and encounter a bug. You step into Umbraco's source code (available through SourceLink) and you learn what's going on. Even better you spot the problem and you have a good idea of how to fix it!
Now in the "olden days" (also known as the .NET Framework days) you would be able to do something like:
- Clone the Umbraco source code
- Find the problematic class and attempt a fix
- Build Umbraco
- Copy the dll and pdb files from that build output to your custom website
- Wait for the site to recycle and observe if the bug is fixed
- Or you could go back to the Visual Studio (VS) / Rider instance where the Umbraco source code is open and attach to the IIS / IISExpress that's running your custom website, set a few breakpoints and use the debugger to get closer to the problem you're experiencing
This workflow used to look a bit like this:
I've personally been doing this for very rapid debugging for years and it has served me very well in Umbraco versions 8 and below, also known as "Classic Umbraco" (thanks Marc Goodson!).
The big caveat here was that if you were to change your custom code in your custom website and do a build in VS/Rider, NuGet would make sure that those dlls that were built straight from the Umbraco source code (including your bug fix) will be overwritten with the officially released dlls for that Umbraco version. So after you build your custom site, you'd have to copy those back in to test your bugfix.
Umbraco 9+
Enter Umbraco versions 9 and above, or "Modern Umbraco" all tranformed to run on a new runtime, dotnet version 5/6/etc (the artist previously know as dotnet core).
The workflow used for .NET Framework does not and can not work any more. When a website is running, there's no way to overwrite dll files new ones, everything is locked. Even if we were to succeed, there's no automatic recyle of the website, so the site will probably just crash.
There is such a thing as "hot reload", which allows use to make code changes and, without building the solution, continuing to use our website. However, I believe that still actually does a build in the background and I don't know what voodoo is does to load the new code, but I doubt we're able to get anywhere near hooking into it. Hot reload is also very limited, it's pretty easy to make a change that's not supported by hot reload and you have to stop and start your site again anyway.
What also would not work was copying in the dll / pdb files when the website was not running. As with "Classic Umbraco", once you run the website it will build and copy the dll files from the official NuGet package back into the site and the code we update would be gone.
We explored different ways of debugging and fixing the Umbraco source code against a custom website in a recent UmbraCollab episode.
UmbraCollab is a weekly event where we find an interesting Umbraco related topic to work on and we try to see how far we can take it in 1 hour, with the help of anyone who wishes to join live. We run UmbraCollab in the voice/video channel on our Discord instance.
We eventually found a nice way of doing a similar type of rapid prototyping and debugging on "Modern Umbraco", with a quite pleasant way to set it up and run a debugger against our custom site.
As a bit of background, the Umbraco source code is a solution that contains many (VS/Rider)projects, and one of those projects is named Umbraco.Web.UI
. This is really "just" a blank Umbraco website, like you would start building if you were to set up your own dotnet new Umbraco
.
We found that we could add our custom website project as part of the Umbraco source solution. I know, right? π€―
In VS/Rider, right-click on the solution and choose to add a project, you can choose an existing project (csproj file) that can live anywhere on your local machine, so in my example I choose D:\Temp\SourceDebug\MyProject\MyProject.cs
Now you should be able to run the MyProject project in the dropdown in Visual Studio:
Or in Rider:
"Magically" from here on in you can alter the Umbraco source code and debug the code, setting breakpoints where you need them. No more copying around dls and pdbs either.
The modern workflow looks a bit like this:
Pretty smooth huh? π
There were two problems we encountered but they don't always seem to happen:
- You might have a bit of a clash with ModelsBuilder models if you use
InMemoryAuto
, so find the folder inUmbracoProject > umbraco > DATA > TEMP > InMemoryAuto
and right-click on it to choose "Exclude" - this way it won't be part of the build - You might have to add two namespaces to your MyProject's
Startup.cs
:using Umbraco.Cms.Core.DependencyInjection;
andusing Umbraco.Extensions;
(because: for some reason, when included in the Umbraco source solution, the<ImplicitUsings>enable</ImplicitUsings>
directive inMyProject.csproj
is not always recognized).
Caveats
There's two caveats to this approach:
- Your IDE (Visual Studio, Rider, etc.) will update the
umbraco.sln
file with the reference to your custom project. If you're planning to contribute your updated code back to Umbraco using a pull request, make sure to revert the changes toumbraco.sln
before you commit and push, then the team of reviewers doesn't have to remind you. - Likewise, your custom project's
csproj
file will now include a reference to the directory where you cloned Umbraco-CMS and if you had to exclude ModelsBuilder files, that will also have been added to thecsproj
file. If you want to keep your colleauges happy, don't commit those changes to source control either.
I always scan whatever changes I'm adding to source control (don't be the git add .
person please, take some pride in what you commit!) so it's easy to revert these changes before committing.
Let me know if you have even more clever ways of doing this in "Modern Umbraco", I'm personally very much enjoying this new approach and it's making me nice and productive!
Top comments (0)