Shaken to the Core about .NET 5?

It’s a dark and stormy night and you wake up with a start: is that the looming feeling of .NET 5 and Umbraco 9 on the horizon?! Upskilling yourself (and your team) can be a daunting prospect for developers, but I’ll guide you through which skills and processes need to change and which you can put on the back-burner. From development environments and .NET 5 concepts to configuration, deployment and hosting - it’s not as big a change as it might sound!

, by Joe Glombek

⚠️ This article was written in and contains out of date information.

A recorded talk containing the same content as this article is also available.

In case you missed the memo, Umbraco 9 won't be running on .NET Framework. All the buzz about Umbraco 9, UniCore, .NET Core, .NET 5 all boils down to this: Umbraco will be running on the brand new .NET 5.

For many people I've spoken to, this is a terrifying prospect. The way we've been working for years or even decades is about to change in a big way - and it's hard to find the time to upskill ourselves and our teams while working full time in earlier Umbraco versions.

.NET 5 is the next step for both .NET Framework and .NET Core and takes over from .NET Standard and Mono too. It opens up a lot of opportunities for us as developers and words like Linux, Docker, containerisation, Visual Studio Code, dotnet templates are popping up all over the place in the Umbraco world. But that's a lot of change to all happen at once - so what's important and what can we put off for a rainy day?

File > New

You might have heard about dotnet templates in the command line and using Visual Studio Code - which you can do, and they're brilliant. But one change at a time, eh?

So for now, lets stick with Visual Studio and create a new Umbraco site using the New Project dialog.

You'll need to enable .NET Core templates in Visual Studio settings first (but for me this was already enabled), and then it's simple as searching for "Umbraco" in the "New Project" window. (You'll also need to add a new Nuget repository if you're working with the beta, but this won't be required once Umbraco 9 launches).

You'll need to enable Options> Environment > Preview Features "Show all .NET Core templates in the New project Dialog"

Create a new project dialog with "Umbraco" entered in the search field.

You'll actually see some improvements from what you're used to in Umbraco 8 thanks to the unattended install process.

You'll be presented with options inside the New Project window to configure your site without having to run through the Umbraco installer.

If you want to use SQL CE (create a database file locally) you'll need to check the "Use SQL Compact Edition" option (or the -ce flag on the dotnet new umbraco statement). Umbraco ships without this my default because it's Windows-only. You won't get the option of a SQL CE connection string if you don't set this flag.

You can also configure a user at this step. But at the moment, you can't use unattended install with a SQL CE database, so pick one or the other.

The Additional Information screen when creating an Umbraco project with the SQL CE flag and unattended install options

After creating the project we'll be presented with a new Umbraco site. It may look a little different, but we'll come onto that later.

Hit the Debug in IIS Express button (no need to use dotnet serve if you don't want to) and you'll see the installer we all know (or, if you used the unattended install, you'll be flung straight into an empty Umbraco site).

Solution structure

Things look a little different in the Solution Explorer. But it's nothing much to be afraid of.

Your views, controllers and other pieces of code, they'll all live in the usual folders.

The main difference you need to be aware of is the wwwroot folder. This is where your static assets are going to live: compiled JS, CSS and related assets. Anything outside this folder will not be served to the browser (except via routing of course). It's a nice peace of mind and saves security rules in your web.config, but takes a little getting used to.

You'll notice the old umbraco folder is now split between ~/umbraco and ~/wwwroot/umbraco, depending on the use case.

Another change you'll notice is the lack of a Web.config file (or any .config file for that matter) and the addition of an appsettings.json...

Configuration

One of the biggest changes you'll see in .NET 5 is with config: everything is an AppSetting. You'll also find some things have moved, but almost everything that was in a .config file will now be in appsettings.json.

Helpfully in VS Code, you get Intellisense for all the property names in appsettings.json - even those specific to Umbraco! Unfortunately, Visual Studio doesn't support the schema ([and I wouldn't hold your breath](Support json schema draft-06 & draft-07 - Visual Studio Feedback)). It's still perfectly usable and no worse than in .NET 4, but it's worth noting this plus for using VS Code.

Because it's JSON rather than key value pairs in config files, settings can now be hierarchical. This means you can find all Umbraco related settings under "Umbraco", logging settings under "Serilog" and uSync settings under "uSync". If you're using an appsetting source that only allows key value pairs (Azure Web Apps or environment variables, perhaps) you can replicate this structure with a double underscore, such as Umbraco__CMS__Hosting__Debug.

I love the new hierarchy and standardisation of all settings this provides. You can also customise the config sources and pull different values from different places in different environments... basically I'm in love with the new configuration. It's what we should've had all along.

C# changes

"[Using .NET 5] is a bit like being in someone else's kitchen. You know that there's stuff that should be there, it might just be in a slightly different place, [...] there might be new things and some of the old things might not be there any more."
Laura Weatherhead, Candid Contributions S2:E9

This is undoubtedly the biggest challenge when moving to .NET 5: libraries have changed and code you're used to writing won't work any more. It can feel a little discombobulating.

That all said, the concepts are generally the same - it's still a "kitchen". It may be a different container, but it's still dependency injection. It may have a slightly different name, but it's still the same method. It might be a different library you need, but it'll still fit the same purpose.

"I know there's a cutlery drawer here somewhere, I just need to find it."
Laura Weatherhead, Candid Contributions S2:E9

If you're anything like me and are a heavy user of Intellisense when you're coding, you should be fine. And any time you'd usually be using a Nuget package, you might just need to do a quick Google search first.

A Google search for "swashbuckler .NET 5"

Packages

There are some pretty drastic changes to the codebase to make Umbraco work in .NET 5 and in a ".NET 5 way". This means package developers have had to do a fair chunk of work to get their packages ready for Umbraco 9.

However, available packages are big factor when deciding whether to upgrade to v9 or not. So let's have a rundown of some of the big ones.

All packages that are front-end only (no C#) should run fine in v9 - the backoffice hasn't changed.

Umbraco Forms & Deploy

HQ have promised that the official Umbraco packages will be in place by the time v9 ships.

uSync

Kevin has already released a beta of uSync! No releases of uSync.Complete or uSync.ContentEdition yet though.

Vendr

Development is underway.

Doc Type Grid Editor

Søren plans to have DTGE complete for v9 launch.

Contentment

Lee is actively working on a v9 version.

Unknown

I can't find any word on: Ucommerce, UmbracoFileSystemProviders.Azure, SEO Checker

Extensibility

A lot of the extension points in Umbraco 8 still exist reasonably unchanged in v9. Content Apps, dashboards and front-end addons can still be created in code or package.manifest files. But for C# 'custom code' there are some changes.

Events/Notifications

If you wanted to extend Umbraco in the past, there's a high chance you'd turn to events. But events no longer exist in v9. (There's a pun in here somewhere about "events being a thing of the past" but I can't work it out.)

Instead we have notifications.

We still create a composer, but instead of reaching for ContentService.Saved +=, we're going to add a notification handler.

public class TestComposer : IUserComposer
{
    public void Compose(IUmbracoBuilder builder)
    {
        builder.AddNotificationHandler<Umbraco.Cms.Core.Notifications.ContentSavedNotification,
            MyContentSavedHandler>();
    }
}

So in our composer, we trigger an AddNotificationHandler with a type parameter of the relevant notification class. In the example above, I'm using a ContentSavedNotification which is the replacement for ContentService.Saved.

The easiest way to work out what notification you need, is to use Intellisense. Fill in the namespace Umbraco.Cms.Core.Notifications. and then hit Ctrl + Space. You'll see a whole list of them pop up.

Intellisense popup with all the Notification classes

The next parameter is your notification handler class. This will implement INotificationHandler (makes sense) with the notification type as the type parameter. Implementing the interface's Handle method, gives you an object very similar to the ContentSavingEventArgs you're used to from previous versions.

using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Notifications;

namespace UmbracoProject.NotificationHandlers
{
    public class MyContentSavedHandler : INotificationHandler<ContentSavedNotification>
    {
        public void Handle(ContentSavedNotification notification)
        {
            foreach (var entity in notification.SavedEntities)
            {
                //Do things
            }
        }
    }
}

Upgrading

Your content will upgrade fine. There are no database schema updates so a v8 database will work in v9.

However, packages, views and custom code will be your issue.

This is how I'd approach a conversion:

  1. Check your packages exist in v9 or, failing that, check for alternative packages.
  2. Check your Nuget packages for .NET 5 versions or alternatives
  3. Install a new v9 instance of Umbraco
  4. Point it at a copy of a v8 database and check the content works ([you can also use uSync to bring across schema and content](Umbraco v8 to v9 migration with uSync - Jumoo Documentation))
  5. Install relevant Umbraco and Nuget packages
  6. Migrate your views and tweak any code to make it compatible
  7. Migrate custom logic (using composers, components and the new notifications pattern)

What's next?

Once you've got your head around .NET 5 and Umbraco 9, what else can we do with it?

Docker/containerisation

Containerisation makes a lot more sense now Umbraco is on .NET 5. It might be worth investigating, especially if you have a complex solution with multiple applications. However, I personally expect this will be overkill for the majority.

Linux hosting

Linux is cheaper than Windows. There are no licence fees which means lower start-up costs for VPS hosting and lower monthly cost for cloud hosting.

But do bear in mind the time and cost of testing your website on a new platform (case sensitivity isn't something we've had to think about much before!) and the time implications of learning the new skills required for DevOps on Linux.

Swap out that IDE

Visual Studio can be a little cumbersome. Once you've got your head around .NET 5, it might be worth looking at Visual Studio Code and the dotnet CLI. They're fast and they're modern. But they do take a little time to get used to.

Linux & MacOS dev machines

Prior to being a .NET dev, I was a Linux user for many years. So once you've switched to Visual Studio Code, why not swap out that OS too?!

Play!

I think the most important next step of all is to play. We've got some new technology available to us that's faster, leaner and more modern. Other developers are excited about .NET 5 and there are some pretty neat projects popping up. Get inspired by them, and do some inspiration yourself - let's see what Umbraco 9 and .NET 5 can do!