A friendly guide to what's moved in Umbraco 8
Many people (some might say hipsters…) were eager to start building sites with Umbraco 8 when it launched in February 2019. After what some might call a shaky start, with subsequent releases the product is rapidly improving. I’ve said on many occasions how it just feels so horrible using Umbraco 7 now I’ve worked with V8’s buttery-smooth interface!
Umbraco 8 was a large rewrite of Umbraco, with many new concepts introduced. One of the biggest criticisms at launch was a lack of documentation of these changes, making it difficult to find the V8 equivalent of something in V7. We should all give the documentation team a massive #H5YR - they’ve been working their butts off for months gradually updating docs and adding detailed how-to guides!
This article isn’t about what’s missing from the documentation per se, but some common things that have tripped me and others up along our V8 journeys so far.
Backoffice
The backoffice UI got a huge overhaul, with a new colour scheme and improved UX. Some standout changes are the sections bar moving from the left to the top, the removal of “tabs” on content items, the “Developer” section being combined with the “Settings” section, and “Packages” repository being moved its own section.
Probably the biggest case of “moved cheese” in the backoffice is found in the context menus that appear when right clicking on a node in the content tree - something that will likely impact most CMS users, not just developers.
If you’re trying to publish a content item directly from the tree, well now you can’t… It’s only possible to publish directly from a content item itself by using the “Save and Publish” button. I would assume this is to stop someone accidentally publishing something! This also means the “publish descendants” option has also disappeared from the tree - you will now find this under the small arrow next to the “Save and Publish” button on a content item.
Publish descendants in Umbraco 8
A feature loved by many - “Change doctype”, the ability to change the doctype used for any node - has gone on vacation for a while… It might return at some point in the future, but it’s not on HQ’s priority list… It didn’t make it into the V8 release as the previous implementation was problematic in many cases.
Previously the context menu at the root of the tree contained an option to “Republish entire site” which regenerated the XML cache - this behaviour has been moved into the “Published Status” dashboard under the “Settings” section. This makes a bunch of sense as it’s content editors who spend most of their time in the content tree whereas as this button in most likely for developers.
Umbraco 8 cache refresh dashboard
Events
In Umbraco 7 you would use an ApplicationEventHandler class to hook into the events that the CMS triggered, for example, to tweak a value before it was saved or to register custom classes like Content Finders.
Event Handlers are replaced by Composers which come in 2 different flavours and replace the familiar ApplicationStarting / ApplicationStarted methods from V7:
- ApplicationStarting becomes **ICoreComposer **- runs while Umbraco is booting up
- ApplicationStarted becomes **IUserComposer **- runs after Umbraco has fully booted up
In 95% of cases you want to be using IUserComposer, as otherwise some Core Umbraco services that you depend upon may not have been initialised yet.
Registering a custom content finder in V7:
public class MyEventHandler : ApplicationEventHandler
{
protected override void ApplicationStarted(…)
{
ContentFinderResolver.Current.Insert<MyContentFinder>();
}
}
Registering a custom content finder in V8:
public class MyComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.ContentFinders().Append<MyContentFinder>();
}
}
The composition parameter in a Composer can be used to register Components, Content Finders, Health Checks, Property Value Converters, Url Providers, Url Segment Providers, + much more - a move away from the Resolver pattern used in V7, and improving discoverability through intellisense.
While the word “Composer” may sound scary, the examples above show how this is more a case of new terminology rather than a drastically new concept. There is in-depth documentation as well as a handy blog series by Stephan Gay explaining how it all works.
Where's all the config?
Umbraco 7 shipped with several XML config files used to configure the application:
- Applications.config - configure CMS “sections”
- Dashboards.config - configure CMS “dashboards”
- ExamineIndexes.config - create Examine indexes and searchers
- ExamineSettings.config - configure settings per Examine index
- FileSystemProviders.config - configure which “file system” Umbraco should use
- Trees.config - configure CMS “trees”
- UmbracoSettings.config - generic Umbraco settings
This was great - it was accessible! It was clear for those trying to find where something was or for those just getting started. In V8 only UmbracoSettings.config remains… So where has all this other stuff gone? How do you configure things now? A large amount of the config has moved into code.
Config-as-code brings a lot of benefits you don’t get with traditional XML files, such as intellisense / autocomplete, and type safety. For Umbraco Core or package devs it can also mean not needing to write messy XML parsers for config files - winning! However this is at the cost of discoverability as the config files aren’t there for you to see. To configure something you likely need to be a C# developer, you need to know which C# classes to implement, and you would need to use Visual Studio to compile your config code. Furthermore in many cases an understanding some of the new concepts in Umbraco 8, such a Dependency Injection and Composition, is necessary too. It’s an interesting shift for a product that prides itself on being FRIENDLY and appealing to a broad group of developers, and there’s a fine line between doing things “right” and a solution working for users.
Dashboards and Sections
Gone are the days where you could manually add a bit of XML to the Dashboards.config file and it would appear in the Umbraco backoffice... Some may be upset, but I think this is a good thing. Too many times have I seen dashboards get wiped out by Umbraco upgrades or by installing packages.
If you’re scrabbling around trying to work out how to create a dashboard in V8, well they can now be registered through a package.manifest file in the App_Plugins folder of your project, like this:
{
"dashboards": [
{
"alias": "myCustomDashboard",
"view": "/App_Plugins/myCustom/dashboard.html",
"sections": [ "content", "settings" ],
"weight": -10
}
]
}
If you prefer C# to JSON, they can also be configured in C# by implementing the IDashboard interface and adding a line like this into a composer:
composition.Dashboards().Append<MyCustomDashboard>();
The same goes for custom sections which can also be configured in either JSON or C# - no more pesky XML files! The Umbraco documentation has fantastic articles with all you need to know about Dashboards, Sections and also Trees.
File System Providers
File System Providers are used to tell different parts of Umbraco, such as the media library, where to store your files. This could be on your local disk, a virtual path, or even a cloud storage service like Azure Blob Storage.
Previously in Umbraco 7, you would configure your connection strings for the filesystem provider from within FileSystemProviders.config - each providers would be configured here using large amounts of confusing XML config. In Umbraco 8 this file is gone and these settings are now configured in appsettings in the web.config - this was an option in V7 too, but not the default. Arguably this implementation is actually friendlier than before, as all Umbraco configuration settings are kept in one place. It also makes it easier to store secure values, such as the Blob Storage connection string, in secure stores such as Azure Key Vault.
One of the most popular packages is UmbracoFileSystemProviders.Azure from Jeavon Leopold, which enables you to store your Umbraco media files on Azure Blob Storage.
At the time of writing v2.0.0-alpha-3 works on Umbraco 8 and it’s on NuGet, but you have to enable pre-release packages in your package manager to be able to install it.
The package has now been split into 3:
- UmbracoFileSystemProviders.Azure
- UmbracoFileSystemProviders.Azure.Media
- UmbracoFileSystemProviders.Azure.Forms
Whereas for the V7 version of the package UmbracoFileSystemProviders.Azure would configure the media library to use Blob Storage, in V8 this purely contains the core file system provider needed to store anything on Azure. In order to configure media storage you must also install the UmbracoFileSystemProviders.Azure.Media library. I’ve seen many people get tripped up by this, installing the core package as they would have done in V7 and not knowing that the Media is also needed in order for it to work as before. It’s another small change to remember, but it makes things like the new UmbracoFileSystemProviders.Azure.Forms library for storing Umbraco Forms definitions possible.
Examine
In Umbraco 7 you could subscribe to an event called GatheringNodeData to populate values in Examine indexes, such as adding new fields or sanitizing values to make them searchable. In Umbraco 8 this event is called TransformingIndexValues. The event behaves in a very similar way, but the implementation differs slightly.
I was pleased to see the search APIs had been cleaned up in V8, though it took a little while to find what I was looking for.
ExamineManager.Instance.TryGetIndex("ExternalIndex", out var index);
var searcher = index.GetSearcher();
var query = searcher.CreateQuery();
query = query.NodeTypeAlias("person").And().Field("nodeName", searchTerm)
var results = query.Execute();
V7 had a method on UmbracoHelper called TypedSearch which returned results as IPublishedContent - you could also call the extension method ConvertSearchResultToPublishedContent directly on the result of a query. I spent hours trying to find an equivalent in Umbraco 8 as the feature is seemingly undocumented, but struck gold when I found ToPublishedSearchResults.
Customising indexes
Arguably 2 of the most config files in Umbraco 7, and the ones that caused most confusion, were ExamineIndexes.config and ExamineSettings.config - for creating indexes and searchers, as well as modifying the ones in core, plus defining which data and fields should be in an index.
Much like other areas of the CMS, indexes are also configured in code in Umbraco 8 - by implementing IUmbracoIndexesCreator. The process for creating a custom index has some pretty clear documentation, and requires a bit more work than previously to get up-and-running, but offers a lot more power to control exactly how the index behaves which just wasn’t possible before.
What about configuring settings of the Core indexes though? This was possible in V7, right?
After a discussion with Examine-guru Ismail Mayat, it turned out a number of people were having difficulty with adjusting the config of Core Umbraco indexes (e.g. Internal / External / Media Index). When I dug deeper it transpired that it’s not possible to change any of these settings without using code - you would need to use dependency injection to replace Umbraco’s Core indexes and re-register them yourself. It seems crazy that anyone who wants to change one setting would have to do this each time, so I created a handy package to make this as FRIENDLY as possible 😉
Using Examine Config you can configure the types to include or exclude, and whether to include protected content items in any Core index directly from the web.config. Settings are configured as appsettings and follow a convention of: Umbraco.Examine.{INDEX-NAME}.{SETTING-NAME}. For example, to enable SupportProtectedContent for the "External" the name would be Umbraco.Examine.ExternalIndex.SupportProtectedContent.
Debugging indexes
For as long as I can remember (well, since the V4 days) Umbraco ran Lucene.NET v2.9.4.1 - which was released in December 2011! 🤯Because of the out-of-date Lucene version, we were also stuck with some pretty archaic tools for working with it.
Those who have worked with Examine may be familiar with the tool Luke - a handy development and diagnostic tool for browsing Lucene indexes, checking a value exists or is what you expected, etc. With Lucene v2.9.1 you need to use Luke v0.9.9.1 (it’s so old, it’s on Google Code!)...
Umbraco 8 takes us one step closer to the modern day, with a jump to Lucene.NET v3.0.3. If you try to open these indexes in Luke v0.9.9.1 you will get all kinds of fun errors. Thankfully I’ve been through this pain so you don’t have to! In order to use Luke with your new Lucene v3.0.3 indexes you need to install Luke v1.0.1 - so shiny and modern it was also released in 2011, but it works!
Conclusion
Amongst some of the more obvious changes, there’s still a handful of sneaky things that can trip you up on your first adventures with Umbraco 8 – from “missing” and moved features, incompatible tools, hidden configuration, and even “disappearing” Blob Storage media (trust me, I lost a whole day to this). The documentation is still THE place to go when you get stuck - it’s evolving constantly thanks to the tireless work of the awesome Documentation Creators and the friendly HQ team. It’s simply impossible to cover all of the different snags someone might come up against, but hopefully over time the cries of “how the hell do I do this?!” will diminish as Umbraco 8 matures and brave people like me experience (and share!) this pain first so others don’t have to ;-)