Vulcan Lightweight Elasticsearch Client for Episerver
Clone or download
Brad McDavid
Brad McDavid Fixed #15 content sync null reference.
bumped version
Latest commit 696152e Sep 20, 2018


Build status

Firstly, what is it not; It’s NOT Episerver Find and it’s NOT supported – not by Episerver, by me or anyone else. If you want a proper, enterprise-level, supported product with fabulous UI and integration, go dig a little in your pockets and get Find.

What is Vulcan?

It is a small, lightweight wrapper around Elasticsearch’s NEST client that provides helpers and tools to index and search for CMS and Commerce content. It’s simple and as it’s Open Source, you can do what you like with it when it comes to extending and customizing it. You can even host your own Elasticsearch instance, so it could be very cost effective!

About Versioning

Starting with 4.x versions, anytime a dependency has a breaking change, such as Episerver 12 or Elasticsearch 6, Vulcan will also update all package major versions to make it simpler for developer consumption. There may also still be other breaking changes introduced as well, but all will Vulcan packages will increment to same major version for each occurrence.

Breaking Changes

Now supports Elasticsearch 5.x!

Much of the project has been rewritten to take advantage of Episerver's dependency injection system. In doing so, many implementations no longer have empty constructors. Also, implementations for interfaces such as IVulcanIndexer and IVulcanIndexingModifier, are no longer discovered, they must be manually registered during Episerver initialization.

To Register IVulcanIndexer implementations, they must be done in an IConfigurableModule as shown below:

public class RegisterImplementations : IConfigurableModule, IInitializableModule
    void IConfigurableModule.ConfigureContainer(ServiceConfigurationContext context)
        // hack: using manual registration as scheduled job doesn't inject otherwise
        context.Services.AddSingleton<IVulcanIndexer, Implementation.VulcanCmsIndexer>();

    void IInitializableModule.Initialize(InitializationEngine context) { }

    void IInitializableModule.Uninitialize(InitializationEngine context) { }

All other interfaces may be registered using the ServiceConfigurationAttribute as noted below

[ServiceConfiguration(typeof(IVulcanHandler), Lifecycle = ServiceInstanceScope.Singleton)]

Another big change is on IVulcanIndexingModifier implementations. The interface has changed from:

void ProcessContent(IContent content, Stream writableStream);


void ProcessContent(IVulcanIndexingModifierArgs modifierArgs);

Where IVulcanIndexingModifierArgs provides the IContent.Content instance and IDictionary<string,object>.AdditionalItems for adding more fields to be indexed. The AdditionalItems property is merged with the main IContent serialization. Below is an example of adding a new field to be indexed:

void ProcessContent(IVulcanIndexingModifierArgs args)
    // index ancestors
    var ancestors = new List<ContentReference>();

    // constructor injected service
    if (_VulcanContentAncestorLoaders?.Any() == true)
        foreach (var ancestorLoader in _VulcanContentAncestorLoaders)
            IEnumerable<ContentReference> ancestorsFound = ancestorLoader.GetAncestors(args.Content);

            if (ancestorsFound?.Any() == true)

    args.AdditionalItems[VulcanFieldConstants.Ancestors] = ancestors.Select(x => x.ToReferenceWithoutVersion()).Distinct();