Preface
This was initially going to be a very short post on how you can achieve this with minimal setup and configuration.
However, reality is almost never as rosy as it initially seems.
In this post I will dive into the many issues and frustrations I faced trying to build a platform using Razor Class Libraries(RCL) and Umbraco.
The idea
I've long been striving to writing a more maintainable architecture for my code projects to help my future self.
It's, as most know, quite easy to make code, but much harder to return weeks, months or years later.
Since my time is pretty short I don't necessarily want to waste time on figure out what goes where and what can be changed without breaking something else.
While doing some research on the different options for .NET, I came across RCL, which on the surface would be easily dropped in on a existing Umbraco platform.
This should allow me to scope each component, page or feature to a class library project.
Separating like this is a bit more work and boiler-plating, but in the end, I can completely scope my focus on the one specific feature I want to work on.
So the main idea for the structure would be;
One main Umbraco Website project with many small feature projects.
The feature projects would then be dynamically loading in development and pre-compiled for production.
The problem(s)
Initially everything was working fine. There were a few kinks, but mostly it was as expected.
Then came the flow of issues, some probably cause by Umbraco, and some by my lack of knowledge on how RCL works.
First it was small inconveniences, like not being able to import from uSync and having to move the templates manually.
But quickly it turned out to be a lot worse.
View files not recognized
The uSync import issues should have been a clear indication that this might not be as "plug-and-play" as I initially thought.
Expanding on this, I noticed that on different environments my templates would not be available at all in the backoffice.
This meant my pages, component etc. would not render since the files were not correctly mapped and not where Umbraco expected them to be.
Umbraco has it's own view locator and some pretty complicated stuff under the hood to support their "in-memory" models workflow.
The rigid system meant that add or overwriting view locators were a complete nightmare and mostly not a viable option.
Many were talking about having complicated pre-build setups that would copy the files locally etc.
However this really did not sit well with me and would really complicate my projects, more then it would help.
So, I went to the best place to get help with Umbraco... The new forums:
https://forum.umbraco.com/t/razor-class-library-and-umbraco-with-runtime-compilation/3488/
The long journey did however also bring forth a new, very annoying issue ⬇️
RCL build time regression
As the title eludes to, a major regression concerning build times with RCL was discovered.
I did notice my builds were quite slow, but initially thought nothing of it.
However, this became a big problem for me since I am using GitHub Actions free tier, which has a monthly build time limit.
Any increase in build time would mean I would be inching closer to hitting my monthly limit, which is not really ideal.
Source: https://github.com/dotnet/aspnetcore/issues/59014
As the time of writing, 21-07-2025, there's still no fix for this and the bug affects both regular ASP projects and also Umbraco.
The solution
Many hours and messages later, a viable solution was proposed on the Umbraco Forums and later confirmed to be working.
It's not quite as pretty and plugable as I would have liked, but it is a viable way forward.
I would still like to improve on the way you have to load each view with a backing controller.
Ideally I would have something generic that I can use to just pickup each view in a RCL project and map it to a controller action.
Maybe it's time to learn about source generators... 👀
RCL build time regression, unfortunately, has no solution for now.
Is it perfect?
No.
But! With the controller based approach(Route Hijacking) I can at least still accomplish my main goal of separating into smaller RCLs.
It still fully works and integrates nicely with Umbraco.
Sure, I can't edit my templates from the backoffice and I have to make some boilerplate code, but that's okay with me.
Conclusion
This was a very long journey spanner over a couple of months, which is far more then I initially estimated this to take.
Though the great knowledge and interaction with the Umbraco community made it all worth it!
I've learned A TON about how Umbraco render engine works, what problems and kinks it has, and the many ways it can be extended.
I also found a working solution to the main problem I set out to solve.
So, working with RCL and Umbraco is very much possible, a bit of a hassle, and hopefully build times will soon improve.
I would probably still recommend using RCL with Umbraco for large projects, especially if the project is on Umbraco V13.
This is because V13 does not suffer from the RCL build time regression bug.
Special thanks
To the Umbraco community for their ideas, ears for listening to my problems and thoughts and for a possible solution.