U17

Posted on June 30, 2026 in umbraco

This site has started as an Umbraco v4.x site, and has been regularly upgraded since then, never completely rebuilt. It has been running Umbraco 13 for about 3 years now, and it is about time to upgrade to Umbraco 17.

Packages

This is the easy part. The solution contains two projects: a Core project, and a UI project. Open each .csproj file, bump TargetFramework from net8.0 to net10.0, bump Umbraco package references from 13.0.2 to 17.4.0, bump a few other packages as per NuGet's suggestions.

The excellent Breaking Changes documentation tells us to remove RazorCompileOnBuild and RazorCompileOnPublish so, let us do it. It also tells us to clean our Program class a little. Remove a .AddDeliveryApi() call, remove a .UserInstallerEndpoints() calls, that is it.

At this point, rebuilding fails.

ModelsBuilderSettings.ModelsMode used to be an enum, looks like it is now a string. Quite simple to fix. Everything that queried the IPublishedContentCache does not compile anymore, porting to IPublishedContentQuery is trivial. There is no IContentService.SaveAndPublish() anymore, apparently, and one needs to Save() then Publish().

All in all, nothing dramatic.

Some of my custom Markdown property editor and converter will not compile, I am going to comment them out for the time being.

And... it builds.

Database

Trying to boot the site fails... with a BootFailedException. A migration seems to want to delete a non-existing constraint named DF_umbracoUser_createDate. A quick Internet search shows that this happened to others as well, so something must have gone wrong with migrations at some point. Not going to troubleshoot, creating the missing constraints before upgrading is quicker:

 ALTER TABLE umbracoUser ADD CONSTRAINT DF_umbracoUser_createDate DEFAULT GETUTCDATE() FOR createDate;
 ALTER TABLE umbracoUser ADD CONSTRAINT DF_umbracoUser_updateDate  DEFAULT GETUTCDATE() FOR updateDate;

And presto... the site upgrades, boots, and I can log into the back-office.

Data Types

A range of data types are gone or have changed. And of course my custom data types are CompletelyBroken™ which is not a surprise, since the back-office UI has been entirely rebuilt.

First, native data types. Basically, go into the Data Types back-office section, and re-assign those that have issues to the proper property type. Rather simple. Weird enough, a content list datatype is throwing in the back-office, because of its orderBy value. Something a migration did not catch? Manually re-saving the datatype fixes it.

And then, I actually use two custom data types:

As far as Markdown is concerned, I was using a property editor in order to support additional custom syntax. Turns out a property editor is not needed anymore, a plain IMarkdownToHtmlConverter implementation is all that is needed. So, the property editor is gone, and it is way nicer this way.

On the other hand the image focus editor needs to be completely rebuilt.

My First Property Editor

There is some nice documentation about property editors in v17, so let us follow it.

mkdir PropertyEditors
cd PropertyEditors
npm create vite@latest ZpqrtBnk.ImgFocus
# with Lit
# with TypeScript
# without Vite RollDown (but I was not proposed it)
cd ZpqrtBnk.ImgFocus
npm i && npm install -D @umbraco-cms/backoffice@17.4.0
rm -rf public/* src/*

Then,

Is all it takes. OK, it takes a bit of time to figure out how to put everything together but hey, this is my very first time with the new UI. The end result is quite polished. As in, it makes way more sense than the convoluted Angular version.

In the end,

npm run build

Drops files in my site's App_Plugins and we are done. As in, it just works. I have to say the experience is quite pleasant.

Models

We are not entirely done with backend work. A few more things have changed, including the CLR type of objects returned by various data types.

The new MediaPicker3 for instance does not return a plain IPublishedContent, but a MediaWithCrops. I do not care about crops. And I had a media converter ensuring that the property value type would be reported as Image in case the picker can only pick one single image. So... that converter needs a bit of update to report the proper type, and to unwrap MediaWithCrops to Image wherever appropriate.

And then, with the various changes applied to property types, I though I would rebuild my models. Turns out they were built using the Our.ModelsBuilder edition of the Models Builder, not the built-in one, because I am using some extra features.

Front-End Time

At this point, I have a running back-office, clean data types (though missing my Markdown converter, but that will be fixed later), everything is nice, time to test the front-end.

And... it does not work.

There used to be Disqus-powered comments here. They got very little engagement, and I am not a big fan of Disqus. So, comments are gone. If you want to discuss this article, your best bet is to ping me on Mastodon.