Custom Modules with Toolkit for Kentico

By Tim Stauffer On June 15, 2020

Custom Modules with Toolkit for Kentico

Why should you create a custom module? 

Kentico has gone to great lengths to make its product, Kentico Xperience, as feature-packed as possible out of the box. Yet, there is always going to be something that it doesn't do because of your unique needs. That is when creating a custom module makes sense. Custom Kentico Modules are very well documented and blogged about, so what else is there to say? Well, as always there are some limitations that I’d like to address and it mainly has to do with how they are packaged. There are currently two ways to create packages and deploy them, using NuGet packages and using Kentico export and import features. Each of them have their own advantages and disadvantages. 

Using NuGet packages

Advantages: Disadvantages
  • You cannot use installation packages to transfer modules for development on other instances – the module becomes sealed and un-customizable after installation
  • You cannot define dependencies between multiple module packages
  • To install or uninstall module packages you need to open the target project in Visual Studio

Kentico export and import

Advantages:
  • Provides an option to leave the packages unsealed and available for further development after import
Disadvantages:
  • Requires manual selection of related database objects for each export package
  • The export cannot transfer DLL files along with the module
  • You cannot define dependencies between multiple modules
  • Installation must be done through the admin interface
  • Uninstalling module objects can be difficult
Both packaging methods have their trade-offs but this leaves a question...

What can be done to make a better package?

When Toolkit for Kentico was originally created, Kentico’s NuGet packaging was still in its infancy. It did not come with adequate functionality to accomplish what we needed it to do which was to work with our Toolkit installer and be installable outside of the Visual Studio environment. Toolkit has several different Extensions that are available to five different Kentico versions (8.2, 9.0, 10.0, 11.0, and 12.0). Our solution allows us to create a Kentico module that can be dropped into the filesystem and automatically install any associated Kentico objects. One of the disadvantages with both of the standard Kentico packaging methods is the lack of dependencies. Several of the Toolkit for Kentico extensions have dependencies on other extensions. By specifying dependencies within the extension we can ensure that all parent UI elements, form controls, and resources are installed before they are needed. Without that menus would be missing and YSODs would be rampant.

How can I create my own module using Toolkit for Kentico?

The steps to create a custom code module with Toolkit Core is very similar to the documented Kentico method. For this example, we are going to create two different modules to demonstrate dependency usage. 

Create Kentico Module Objects

To start we will create the two new modules within the Kentico admin. When creating the extensions be sure to set a version. This will be used to determine whether or not your module objects need to be updated when installing newer versions of your module.


Creating DancingGoatExtensions Module

Our first module in my example is DancingGoatExtensions. Make sure the code name is somewhat unique as to not step on the feet of other modules you may install.

naming your module

Create a menu UI element as a parent for our other module.

Creating a menu UI element as a parent for our other module

Create a second module named DG Coffee

Again remember to set the module version.

Setting the module version

Create a new UI element named Coffee under the Extensions UI Element

Creating a new UI element named Coffee under the Extensions UI Element

For simplicity, in this example be sure to check Is Global Application and Requires Global administrator privilege level. This just makes it easier for the new elements to show up in the menu. For more information see the documentation on Managing UI Elements 

Checking "Is Global Application" and "Requires Global administrator privilege level"

You should now see your new modules UI elements in the left menu.

New modules showing elements on left menu

Creating Object Packages

Now that we have our module objects created in Kentico we need to create some object packages to be used in our custom code extension. To do this we need to Export both of the modules.

Exporting modules

Step 1 of exporting module

Step 2 of exporting module

Be sure to download the created package or go to the path specified.

Step 3 of exporting module

Repeat the same process for the DancingGoatCoffee module.

Creating Custom Code

Now that we have our object packages it’s time to write some code. Our custom code is going to live in separate projects from our CMSApp project. This makes it easier to keep code organized and also allows us to reuse code on other projects. You can right-click on the solution and go to Add and select New Project.

We are going to create a new Class Library(.NET Framework) and the first project name is going to match our module names with a target framework to match the framework used by the CMSApp project. In our case, we’ll target .NET Framework 4.6.1.

creating a new Class Library(.NET Framework)

creating a new Class Library(.NET Framework)

creating a new Class Library(.NET Framework)

Repeat this process for the Coffee Extension.

creating a new Class Library(.NET Framework)

Delete the Class1.cs files generated by Visual Studio, we are not going to use them.

Deleting the Class1.cs files generated by Visual Studio

Installing The NuGet Packages

Each module needs the following packages installed: See Quickstart: Install and use a package in Visual Studio for instructions on how to install NuGet packages.


Setting References

Now we need to add a reference in the DancingGoat.Coffee project to the Extensions project so we can set dependencies. We also need to add a reference in the CMSApp project to our two modules

setting refferences

In the DancingGoat.Extensions project creates an Extensions Extension class. This class contains all the Meta information for your package such as the Kentico Module object name and the exported object archive name along with the path the archive will be located.
using System.Collections.Generic;
using BizStreamToolkit.Core.Abstractions;
using BizStreamToolkit.Core.Models;

namespace DancingGoat.Extensions
{
    public class ExtensionsExtension : Extension
    {
        public ExtensionsExtension()
        {
            ModuleName = "DancingGoatExtensions";
            ArchiveName = "DGExtensions.zip";
            PackagePath = "/CMSModules/DancingGoatExtensions/ObjectPackages/";
            // version set in AssemblyInfo.cs
            Version = GetType().Assembly.GetName().Version;
            ExtensionDependencies = new List<iextension/>();
        }
    }
}
Do the same for DancingGoat.Coffee with one difference, we are specifying DancingGoat.Extensions as a dependency.
using System.Collections.Generic;
using BizStreamToolkit.Core.Abstractions;
using BizStreamToolkit.Core.Models;
using DancingGoat.Extensions;

namespace DancingGoat.Coffee
{
    public class CoffeeExtension : Extension
    {
        public CoffeeExtension()
        {
            Name = "DG Coffee";
            ModuleName = "DancingGoatCoffee";
            ArchiveName = "DGCoffee.zip";
            PackagePath = "~/CMSModules/DancingGoatCoffee/ObjectPackages/";
            // version set in AssemblyInfo.cs
            Version = GetType().Assembly.GetName().Version;
            ExtensionDependencies = new List<IExtension> {new ExtensionsExtension()};
        }
    }
}
Extensions Module
using BizStreamToolkit.Core.Models;
using CMS;
using DancingGoat.Extensions;

[assembly: RegisterModule(typeof(ExtensionsModule))]
[assembly: AssemblyDiscoverable]

namespace DancingGoat.Extensions
{
    public class ExtensionsModule : ToolkitModule
    {
        public ExtensionsModule() : base(nameof(ExtensionsModule), new ExtensionsExtension())
        {
        }
    }
}
Coffee Module
using BizStreamToolkit.Core.Models;
using CMS;
using DancingGoat.Coffee;

[assembly: RegisterModule(typeof(CoffeeModule))]
[assembly: AssemblyDiscoverable]

namespace DancingGoat.Coffee
{
    public class CoffeeModule : ToolkitModule
    {
        public CoffeeModule() : base(nameof(CoffeeModule), new CoffeeExtension())
        {
        }
    }
}

So, what is so special about the ToolkitModule? Basically it is a subclass of the CMS.DataEngine.Module class. The ToolkitModule adds a PostStart.Execute event handler that runs and checks to see if the module or any dependencies need to be installed or updated. This can be overridden to give additional functionality.

The code is complete, time to package it up. When you build the project DLL files for your modules will be placed in the bin directory of the CMS app. 

Create a new folder for each new module package; names don't matter. We are only concerned about what’s inside.

DancingGoatExtensions
  • bin
  • CMSModules\DancingGoatExtensions\ObjectPackages
  • CMSModules\DancingGoatExtensions\ObjectPackages\DGExtensions.zip
DancingGoatCoffee
  • bin
  • CMSModules\DancingGoatCoffee\ObjectPackages
  • CMSModules\DancingGoatExtensions\ObjectPackages\DGCoffee.zip

You can add the files to a zip file or copy them into any Kentico installation (must match your development version).

So, What’s next?

If you’ve made it this far I thank you for reading. Writing custom code can be very complex and I hope I’ve helped you understand a new concept or introduced you to a new product. Using the modules that we created will allow you to extend your Kentico customizations even more as well as tailor the module installations to your specific business needs.

Share This Post:

Twitter Pinterest Facebook Google+
Click here to read more posts
Start a Project with Us
Photo of the author, Tim Stauffer

About the author

Completely self-taught and a Jack of all trades, Tim’s the man when it comes to making things happen with websites and software. Given enough time, he can figure anything out. It makes him feel all warm and fuzzy inside when he makes something and others use it to make their lives better. We like his big heart. Tim enjoys “experimenting with food,” and is just a bit addicted to World War II movies.

View other posts by Tim

Subscribe to Updates

Stay up to date on what BizStream is doing and keep in the loop on the latest with Kentico.