How to Run Umbraco with Angular and Docker

How to Run Umbraco with Angular and Docker

In this post, we'll discuss How to Run Umbraco Rest with Angular and Docker

Introduction 

Nowadays, we all see and hear tons of PoC and software solutions based on front-end frameworks, .NET backend, and containerization; with the spreading of .net core and its multi-platform nature, we have now opened a whole world of solutions that we couldn’t see before and that will speed up our developments and open us the possibility of developing better and faster web apps. I really love developing on macOS with Visual Studio Code, exploiting an API/backend solution with .NET Core and a front end made with Angular, putting all in a Docker container...fast, eventually scalable, light and friendly with all the most recent DevOps technologies.

But one of the biggest faults in Microsoft world is CMS. One of the best solutions by now is Umbraco CMS, which unfortunately in its last version (8) has not been ported to .NET Core yet.

So what could we do? Do we have to forget about Angular and containers since we are jailed inside Microsoft OS?

Of course not! In this guide, thanks to Docker Windows containers, I’ll show you how to make a little web page sample with Angular front end and data taken from the API layer served by Umbraco CMS, all developed and deployed inside a single Docker container.

This is the reason why we use a package plug-in for Umbraco called Umbraco HeadRest, developed by Matt Brailsford (https://github.com/mattbrailsford/umbraco-headrest).

Note that Umbraco has now a cloud solution like this - called Heartcore - but the HeadRest solution is definitely better for developing purposes and deep website customization since you have control over all features of the API layer.

This is image title

Let’s start!

Software and products needed on your dev machine,

  • Docker for Win

  • Visual Studio 2019 (for the .NET code)

  • Visual Studio Code (suggested for the Angular code but you can choose your favorite dev environment)

First, we need a database, the better choice for Umbraco is MSSQL; Umbraco could work with other DB engines too.

I suggest you Azure SQL database service DB, which is mostly the best solution but you can choose your own one. For example, keep the DB on the same container of the web app or put it in another separate container.

After you set up the DB, you can create a new Web Application directly from Visual Studio 2019. Enable the Docker support in order to debug and deploy the application inside a container.

Then, install Umbraco CMS from Nuget Package Manager (version used in this article is 8.4.0, but is already available v8.5.3 with some major changes). We also need the API layer package installed that will serve the Angular frontend, the “magic” one, so search for Our.Umbraco.HeadRest.

This is image title

Then, let’s start the website inside the container to create some backend stuff.

I started creating a home page sample with a proper title and a first-level page sample with, again, a proper title.

Now, let's move to configuration to let HeadRest do its work. If you read the GitHub project page info you can understand it's mandatory, I’ll explain what I have done to set it up properly, in order to make the process easier.

We have to implement the Umbraco 8 Component and Composing method: essentially, these are the new ways that Umbraco gives us to register and configure components at the application startup.

For further info, read:

Basically, IComponent is an interface for code that should be initialized and terminated by Umbraco automatically when the application starts, the dependency injection stepson of ApplicationEventHandler.

So we configure our HeadRest like this:

    public class HeadRestConfigComponent : IComponent  
    {  
        private readonly HeadRest _headRest;  

        public HeadRestConfigComponent(HeadRest headRest)  
            => _headRest = headRest;  

        public void Initialize()  
        {  

            // Configuration goes here  

            _headRest  
             .ConfigureEndpoint("/api/", "/root//homePage[1]", new HeadRestOptions  
            {     
                //CustomRouteMappings = new HeadRestRouteMap()  
                //    .For("^/(.*)?$").MapTo("/"),  

                ViewModelMappings = new HeadRestViewModelMap()  
                .For(HomePage.ModelTypeAlias).MapTo<HomePageViewModel>()  
                .For(FirstLevelPage.ModelTypeAlias).MapTo<FirstLevelPageViewModel>()  
            });  
        }  

        public void Terminate() { }  

    }  

We’ll have an API layer configured on the path/API of our web app, starting from the homepage node of the Umbraco tree; we also configure our view model map, which should be the view model that will be on our document type (HomePage and FirstLevelPage document types) and will be outputted in the API layer data.

I usually put all the “compiled” items (like controllers and the component initialization in this case) in an external project, to have cleaner code and a better solution organization.

The HomePage and FirstLevelPage classes have been automatically generated by Umbraco with the ModelsBuilder live DLL method, and the DLL has been imported in the external project.

This is image title

In order to let Umbraco pick up the component, it must be added to the Composition like this:

    [ComposeAfter(typeof(HeadRestComposer))]  
    public class HeadRestConfigComposer : IUserComposer  
    {  
        public void Compose(Composition composition)  
        {  
            composition.Components()  
                .Append<HeadRestConfigComponent>();  

            composition.WithCollectionBuilder<MapDefinitionCollectionBuilder>()  
                .Add<HeadRestMapDefinition>();  
        }  

    }  

We also need to tell HeadRest how to map our view model classes with the document ones, and we use a map definition class to do it:

    public class HeadRestMapDefinition : IMapDefinition  
    {  
        public void DefineMaps(UmbracoMapper mapper)  
        {  
            mapper.Define<HomePage, HomePageViewModel>                         (HomePageViewModelMapping.Instance.Map);  

            mapper.Define<FirstLevelPage, FirstLevelPageViewModel>  (FirstLevelPageViewModelMapping.Instance.Map);  

        }  

    }  

With the field specification mapping:

    public class HomePageViewModelMapping : BaseMapping<HomePageViewModelMapping,  HomePage, HomePageViewModel>  
    {  
        public override void Map(HomePage src, HomePageViewModel dst, MapperContext ctx)  
        {  
            // Base mappings  
            //BasePageViewModelMapper.Instance.Map(src, dst, ctx);  

            // Custom maps  
            dst.Title = src.Title;  
        }  
    }  

The BaseMapping class defines a better way if we have some common fields in our document types:

    public abstract class BaseMapping<TSelf, TFrom, TTo>  
        where TSelf : BaseMapping<TSelf, TFrom, TTo>, new()  
        where TTo : new()  
    {  
        private static readonly Lazy<TSelf> lazy = new Lazy<TSelf>(() => new TSelf());  
        public static TSelf Instance { get { return lazy.Value; } }  

        protected BaseMapping()  
        { }  

        public TTo Map(TFrom src, MapperContext ctx)  
        {  
            var dst = new TTo();  
            Map(src, dst, ctx);  
            return dst;  
        }  

        public abstract void Map(TFrom src, TTo dst, MapperContext ctx);  
    }  

Now we can test our API layer. If you launch the application and go to http://{container address}/api/ you should get a JSON response with your homepage property name and value.

That’s it, so let’s move to Angular!

Create and keep your working folder at the same level as the folder containing the website (I have a “front-end” folder on a par with the Umbraco web app). Then, using Visual Studio Code, install the basic Angular components in that folder with NPM and NG commands.

Create your needed Angular models based on the Umbraco document view models, set up the API URL endpoint to “/api” and try to output the title data in the home page.

Obviously, this is a very basic example, since it's not the main topic of this article.

Now we have to do three things:

  1. Let Visual Studio automatically compile and copy the Angular part from its folder to the website root
  2. Tell Umbraco to exclude our main index.html Angular page from its handling flow
  3. Tell our webserver to automatically land the web app on that page.

To accomplish the first task, we use the project pre-built events; since they will be executed every time the build is launched, we can insert the Angular compile and copy the part into that place.

Here's what I did:

echo "cd $(SolutionDir)" &&^  
cd "$(SolutionDir)\frontend" &&^  

echo "Building Project" &&^  
ng build &&^  

echo 'copy files' &&^  
xcopy "$(SolutionDir)\frontend\dist\frontend" "$(ProjectDir)" /Y  

Echos are for debugging purposes only.

I had some trouble with the NG command inside the event command line, so if Visual Studio does not recognize it, I advise you to go and check if it had been added to environment path variables. Restart the computer if necessary.

As you can see from the commands, we are placing the path inside the Angular part folder (frontend), then we launch the build for the Angular part that will place the results inside the dist\frontend folder, and copy all that files in the website root.

So, here we have our website with our pre-compiled Angular files all together but Umbraco still doesn’t know that it should not handle requests to our index page.

In order to avoid this, we have to add our needed ignore paths to the web.config file in the appSettings region. 

<add key="Umbraco.Core.ReservedUrls" value="~/index.html,~/" /> 

Well done! If you type http://{container address}/index.html you can now see your Angular front-end page calling your API served by Umbraco!

Last thing: tell the web server that our default page must be the index one, so add this part too in the webconfig in the system.webServer region:

      <defaultDocument>  
        <files>  
          <clear />  
          <add value="index.html" />  
        </files>  
      </defaultDocument> 

Now, we can reach the index page simply typing http://{container address}/.

You can go on using a lot of options offered by Angular: insert the container in a DevOps lifecycle to deploy it and so on...

If you want to add an authentication to your web app, as suggested by Matt Brailsford in his Umbraco HeadRest git repo, you can go for his oAuth2 solution called Umbraco authU https://github.com/mattbrailsford/umbraco-authu

Our.Umbraco.AuthU on nuget.

I hope that Umbraco will be ported to .NET Core as soon as possible; the project is going on and looking for contributors so finally we’ll have all the big advantages that .NET Core is giving us, cause Umbraco is undoubtedly one of the best and most consolidated CMS solutions in the .NET world.

Leave feedback if you want!

angular docker c# API umbraco

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Top 10 API Security Threats Every API Team Should Know

Learn what are the most important API security threats engineering leaders should be aware of and steps you can take to prevent them

Docker Explained: Docker Architecture | Docker Registries

Following the second video about Docker basics, in this video, I explain Docker architecture and explain the different building blocks of the docker engine; docker client, API, Docker Daemon. I also explain what a docker registry is and I finish the video with a demo explaining and illustrating how to use Docker hub.

Docker Tutorial for Beginners 8 - Build and Run C++ Applications in a Docker Container

Welcome to this on Docker Tutorial for Beginners. In this video provides an Introduction on C++ development with Docker containers. So we will see How to ship C++ Programs in Docker.

Angular 10 Docker Tutorial | Dockerize Angular App and Deploy to Docker Hub [ STEP BY STEP GUIDE]

Hey Guys , As you can see in the starting of the video, our localhost 4200 was not responding, why this never happened to us in previous videos.? That’s Because the node server is not up and running anywhere in the whole system. Angular 10 Docker Tutorial | Dockerize Angular App and Deploy to Docker Hub [ STEP BY STEP GUIDE]

What Are Good Traits That Make Great API Product Managers

What is API product management and what can you be doing to be a better API product manager — get aligned with SaaS and enterprise software requirements. This guide lays out what is API product management and some of the things you should be doing to be a good product manager.