Skip to main content

Umbraco Package Migration to .NET Core: A False Start

This is one of a series of posts looking at migrating Umbraco packages to V9 and .NET Core. Other posts in this series:

  1. Introduction
  2. A False Start
  3. A Clean Start - Controllers, Services, Configuration and Caching
  4. Criteria Providers - Working With HttpContext
  5. Leaning on Umbraco
  6. Migrating Tests
  7. Extension Methods
  8. Migrations
  9. Wiring It All Up
  10. Distributing and Wrapping Up

One Codebase or Two?

The first decision I took on migrating Personalisation Groups to Umbraco V9 running on .NET Core was on whether to attempt to maintain a single code-base for the supported versions. A couple of years ago, I wrote an article for Skrift outlining the approach I took when V8 came out, which was to maintain versions for V7 and V8 in the same source code repository and in the same branch.

In summary, the approach I took there was to extract, from what was then a V7 package, the common code that had no dependency on Umbraco at all. There turned out to be quite a bit of it, which could move into a "core" project that didn't take a dependency on Umbraco. I then referenced that from two other projects, depending on V7 and V8 Umbraco NuGet dependencies respectively, where the parts of the implementation that touched Umbraco APis were written, as necessary for the two versions. And I can say in hindsight this has worked actually out quite well. There's not a huge amount of active development done on this package, but what I have done has been able to be applied to both versions, which remain functionally equivalent.

So the question was, could I, or should I, try to do the same for V9? This would mean migrating the core project to .NET Standard, such that it could be referenced both by the two current projects, and a new one, referencing Umbraco 9.

And the answer? Could I... well maybe, should I... I think not. I'll share where I got to and my thought process though.

Project Migration

I did make a start, the first necessary step being converting the means of referencing packages from the legacy packages.config file to use PackageReference in the .csproj file. This worked mostly OK, though for one project I did run into an issue where the automatic migration failed with an error of "migrate packages.config to packagereference project is not eligible for migration", which was solved via this tip.

With that done, the next stage was to fully migrate to the new .csproj format. This newer version is much simpler from what we're used to in earlier .NET Framework, mainly as there's no need to list every file. There's an excellent guide for doing this here, which I followed for one project and found all worked as expected.

I was when I started to look to update the code to be .NET Standard compatible though I began to question whether this approach was going to be a good idea. Some of the issues I found and resolved before giving up were:

And I possibly could have continued in that vein.

Starting Over

However it did seem like I was biting off more then necesssary in attempting to support three versions of Umbraco, and two frameworks, in the same package - particularly for the amount of active development there is on it. I also was noticing a number of compromises I'd made along the way, and would need to do in future, around best practices - particular in the lack of use dependency injection. As this only really became a first-class citizen in Umbraco V8, by supporting V7, I'd opted for a fair bit of use of static classes, and newing up of components, that I'd really like to avoid. And with dependency injection being perhaps even more a best practice supported by .NET Core, this didn't seem a good way to proceed.

I suspect others, with more active development and a pragmatic choice to support just two Umbraco versions (V8 and V9) may investigate this approach more fully - but I've decided to keep what I have as is, supporting V7 and V8, and start a new greenfield repository for V9. Which will also have the benefit of being able to fully adopt best practices and new approaches without having to compromise for backward compatibility.

A half-way house - which is what Umbraco have adopted for the CMS development and likely will also do for the HQ supported packages - is to use one repository, but a separate branch. This allows the code to be separate, but makes it easier - though not easy as they start to diverge - to merge between branches and port features or bug-fixes from one to the other. For my case though, as supporting just V9 would allow some simplification of the solution structure, a separate repository altogether seemed a better bet.