Skip to content

Use Initialization Modules

⏱ 15 minutes intermediate

Many CMS customizations need to run once when the application starts — registering event handlers, configuring custom services, or seeding initial content. Initialization modules give you a structured hook into the CMS startup pipeline. They run after the CMS framework is ready but before the first request is served.

  1. Create a class that implements IInitializableModule
  2. Add the [InitializableModule] attribute
  3. Use dependency attributes to control execution order
  4. Test that your code runs on application startup
Simple initialization module
csharp
using Optimizely.Cms.Core;
using Optimizely.Cms.Framework.Initialization;

namespace MySite.Initialization;

[InitializableModule]
public class SiteInitialization : IInitializableModule
{
    public void Initialize(InitializationEngine context)
    {
        // Runs when the application starts
        Console.WriteLine("Site initialization complete.");
    }

    public void Uninitialize(InitializationEngine context)
    {
        // Runs when the application shuts down
        // Clean up event handlers and resources here
    }
}

The CMS discovers modules automatically by scanning assemblies. You do not need to register them manually.

When your module depends on another module being initialized first, use the [ModuleDependency] attribute.

Module with dependencies
csharp
using Optimizely.Cms.Core;
using Optimizely.Cms.Framework.Initialization;
using Optimizely.Cms.Core.Initialization;

namespace MySite.Initialization;

[InitializableModule]
[ModuleDependency(typeof(CmsCoreInitialization))]
public class ContentEventModule : IInitializableModule
{
    public void Initialize(InitializationEngine context)
    {
        var events = context.Locate.Advanced
            .GetInstance<IContentEvents>();
        events.PublishedContent += OnContentPublished;
    }

    public void Uninitialize(InitializationEngine context)
    {
        var events = context.Locate.Advanced
            .GetInstance<IContentEvents>();
        events.PublishedContent -= OnContentPublished;
    }

    private void OnContentPublished(
        object? sender, ContentEventArgs e)
    {
        // React to content publish
    }
}

Key points:

  • CmsCoreInitialization ensures the content repository is ready before your module runs.
  • Always unhook events in Uninitialize to prevent memory leaks during application recycling.

Register services with configurable modules

Section titled “Register services with configurable modules”

Use IConfigurableModule when you need to register services in the dependency injection container.

Configurable module for DI registration
csharp
using Optimizely.Cms.Core;
using Optimizely.Cms.Framework.Initialization;
using Microsoft.Extensions.DependencyInjection;

namespace MySite.Initialization;

[InitializableModule]
public class ServiceRegistrationModule : IConfigurableModule
{
    public void ConfigureContainer(ServiceConfigurationContext context)
    {
        context.Services.AddSingleton<IEmailService, SmtpEmailService>();
        context.Services.AddScoped<IPricingEngine, CustomPricingEngine>();
    }

    public void Initialize(InitializationEngine context)
    {
        // Additional startup logic after DI is configured
    }

    public void Uninitialize(InitializationEngine context) { }
}

ConfigureContainer runs before Initialize. Use it exclusively for service registration. Put runtime logic in Initialize.

A common use case is creating default content on first startup.

Seed content on startup
csharp
using Optimizely.Cms.Core;
using Optimizely.Cms.Core.Repositories;
using Optimizely.Cms.Framework.Initialization;

namespace MySite.Initialization;

[InitializableModule]
[ModuleDependency(typeof(CmsCoreInitialization))]
public class ContentSeedModule : IInitializableModule
{
    public void Initialize(InitializationEngine context)
    {
        var repo = context.Locate.Advanced
            .GetInstance<IContentRepository>();

        var startPage = repo.GetDefault<StartPage>(
            ContentReference.RootPage);

        if (startPage == null)
        {
            var page = repo.GetDefault<StartPage>(
                ContentReference.RootPage);
            page.Name = "Home";
            page.Heading = "Welcome";
            repo.Save(page,
                Optimizely.Cms.Core.SaveAction.Publish);
        }
    }

    public void Uninitialize(InitializationEngine context) { }
}
IssueCauseFix
Module never runsMissing [InitializableModule] attributeAdd the attribute to your class
Null reference in InitializeDependency not yet initializedAdd [ModuleDependency] for the required module
Events fire twiceModule initialized twice during recycleUse a static flag or check before subscribing