In this tutorial, you will learn how to create a kick-ass content app within Umbraco 9. The differentiator with this tutorial, compared to some others online is that we will create everything using C#. No Angular, no messing about with JS, it's all C# baby!

Within the Umbraco universe, a Content App is a custom screen that you can magically make appear on a per-page basis within the backend. Whenever a content editor creates or edits a new page within the CMS, a new tab will appear next to the 'Info' tab. Clicking on the tab will load a custom screen. It is then left up to your creativity to decide what will load 🤔

The options are endless, you could create an app that displays page related analytics, links to social sites, or whatever your tiny little mind can invent. The example content app that we will be building out within this tutorial will provide a short link generator capability for the current page. The app will render a button, that when clicked will call Bitly.com, generate a short link and copy it to the clipboard automatically.

I will warn you now... there will be a slight surprise when it comes to building this app. Unpublished pages do not have URLs. This means we will also delve into how Urls are constructed within Umbraco and we will need to come up with a workaround for yet to be published pages. I hope this extra complexity will allow you to learn a lot more about this powerful CMS. If you want to learn how to take your Umbraco project to the NEXT level, read on 🔥🔥🔥

How To Create A ContentApp

To create a content app, the first step is to register a new app within Umbraco using IContentAppFactory. First, create a new class and inherit from IContentAppFactory. After doing this, you will need to implement GetContentAppFor(). Within GetContentAppFor(), you will need to add the registration code to call your custom code. When this call has been made, you can call a custom vanilla controller and render the HTML:

As we solely want to use C# to create this content app, we have a dilemma. By default, a content app will be rendered without any context about the page around it. This poses a pretty significant problem. We need access to the current pages contextual information to do anything useful in the app. At a minimum, you will need to have access to the current page Id within your content app controller. How do we get this?

You may find the process of getting this Id counterintuitive. You do not get context about the current page from the controller, you will need to pass this data from IContentAppFactory instead. This is possible due to how IContentAppFactory is called 🤔

Whenever a content editor tries to edit a page in the CMS, on each request the custom IContentAppFactory class will be triggered. When this trigger occurs, the current page's context will be passed into the custom IContentAppFactory . You can then access this data and pass it onto the controller. You can see this magic on Line 24, where I pass the page Id into the Url!

They key thing to get this working is routing. In order to get the routing to work, you will need to add a custom routing rule into your application's route table. With the rule in place, the controller will be called and it will be passed the page Id. Using this Id you can then get information about the page using the normal Umbraco APIs.

As we are working with a backend screen you also need to think abut security. Umbraco does not want any Tom, Dick, or Harry accessing any backend screen, so they have included a useful mechanism for developers to easily secure backend screens. To implement a secure screen, the Url to trigger the content app controller needs to start with umbraco/backoffice/plugins/.

Keep in mind that CMS routing rules are different to normal vanilla MVC rules. Within an Umbraco site, to load anything non-Umbraco related, you need to manually register the Url you want to enable within the route table. The code to register an appropriate routing rule is shown below:

This rule then needs to be registered within Start.cs like this:

Another point worth mentioning is that Umbraco will also not load your custom IContentAppFactory class magically, you will need to register it. This is done using a composer. The code to create this composer is shown below:

With the content app registered with Umbraco and the correct routing rule enabled. The rest of the code is pure C# MVC!

Creating An Umbraco Content App

The first step is to create a controller. You can use a normal vanilla MVC controller to do this:

Theres some funky looking code in this Index action. That code is used for building the Url (remember nonpublished pages do not have URLs in Umbraco). Getting the Url for a published item is dead simple. Umbraco has two content states. Published content and non-published content. Anything that is live on the website is published and it will be added to a front-end cache. Any published bit of content can be accessed using the IPublishedContent type. IPublishedContent exposes the Url() method.... simple!

Internal content can still be accessed in code, howewer, you need to use different APIs and you will be working with different types. Internal content is accessed using the IContentService. IContentService will return content as type IContent. IContent does not contain a Url() property. This is why you will need to build this functionality yourself for non-published content.

Some experienced Umbraco developers might claim that the following code is not best practice, however, needing to plan content campaigns is a very valid content editing need. Just be warned that you are going against the grain slightly with this code.

The code to create a URL for internal content can be seen on Line 24. I get the parent node which I assume is published and get its Url. This gives me access to the majority of the final Url, minus the segment for the current page.

Even though the page might not be published, you can call the published API in preview mode to get certain data about an internal page like its Url segment! To get the current page segment in preview mode, I use this code .GetById(true, id);. The true being passed in is the thing that enabled preview mode!

This preview call will get a unpublished item in IPublishedContent format. Using the UrlSegment property, you can then get that items Url. Finally, combine the parent URL with the current page segment and you have a complete Url!

Yes.. this is very long-winded, unfortunately, Umbraco is not great at managing unpublished content. With the code nailed, it's time to create an associated view. Create a new view here:

Views âž¡ AdditionalLinks âž¡ Index.cshtml

Within the view add all the HTML required to render the app. This example includes all the Javascript to ping the Bitley API and to copy everything to the clipboard:

The HTML looks complex, however, all it's doing is calling Bitley and adding stuff automatically to the clipboard. It is worth noting that you will need a Bitley API key and a valid account for this to work. A key is generated within the Bitley portal from the Settings section. With everything in place, when you load your site, you should now have a working content app!


You now know how to create killer content apps within Umbraco v9 💥. Content apps can be leveraged to provide a wealth of extra information and functionality to content editors. If you want to take your Umbraco builds to the next level in terms of quality and usability, master these to become an absolute legend! Happy Coding 🤘