Episerver Event Helper v3.0

Years pass and hopefully you learn something and become better!

One thing that have been poking on my conscience for a while is the old EPiEventHelper that I blogged about a couple of years ago.

What’s wrong with it?

There are two things I don’t like with it.

1) Unclear usage

I have seen that it has been some confusion with how to best access the content – using the eventArgs.Content or using this.

public class StandardPage : PageData, IPublishingContent
{
    public void PublishingContent(object sender, ContentEventArgs e)
    {
        // this is how to access the already cast instance of the content.
        StandardPage standardPage = this;

        //This is the content from the argument, needs to be casted to your Content Type. But to me it feels more correct.
        IContent contentFromArgument = e.Content;
    }

}

A common question is if the e.Content and this are two different instances (they are the same) and which one should be used (honestly I don’t have a recommendation).

2) Single Responsibility Principle

The second thing is that this implementation violates the Single Responsibility Principle. The class representing your Content Type should been seen as a View Model or Data Model and therefore it should not contain any behavior or business logic.

I have seen some examples where the logic found in the event is really large, making the Content Type class very messy and hard to understand.

Presenting – EPiEventHelper 3.0

What? Why 3.0?

Pavel Nezhencev already created a NuGet package with EPiEventHelper and later upgraded it to use Episerver 10, calling it version 2.0. If I want to publish my version with new features to NuGet.org I need to bump the version even further.

What’s new?

First of all I have stopped checking if the current Content implements the event interface. Instead I’m using to use the IoC container in Episerver where you as a developer can add your own things.

This means that you will need to decorate your implementations of the interfaces with the ServiceConfiguration attribute.

[ServiceConfiguration(typeof(IPublishingContent))]
public class PublishingContentEvent : IPublishingContent
{
    public void PublishingContent(object sender, ContentEventArgs e)
    {
        IContent content = e.Content;
        var standardPage = content as StandardPage;
        if (standardPage == null)
            return;

        // Do something with your standard page
    }
}

Breaking change: This also means that if you are using the previous version of EPiEventHelper, you can no longer refer to the content using this!

public void PublishingContent(object
    sender, ContentEventArgs e)
{
    this.Name = "Hello World!";
}
public void PublishingContent(object
    sender, ContentEventArgs e)
{
        e.Content.Name = "Hello World!";
}

Breaking change: The interface does not know anything about the class representing your Content Type and therefore you will need to cast e.Content yourself!

public void PublishingContent(object
    sender, ContentEventArgs e)
{
    this.Title = "Hello World!";
}
public void PublishingContent(object sender,
    ContentEventArgs e)
{
        var content = e.Content as StandardPage;
        if (content == null)
            return;

        content.Title = "Hello World!";
}

Unless…

I have created a workaround for this where you can have the same pattern to bind the Episerver events, but only apply if to specific Content Types AND the Content will also be typed!

New functionality: Each interface have an abstract base class where you specify which Content Type class you want to use. As usual you use the ServiceConfiguration attribute to bind your implementation to the event.

[ServiceConfiguration(typeof(IPublishingContent))]
public class PublishingStandardPage : PublishingContentBase<StandardPage>
{
    protected override void PublishingContent(object sender, TypedContentEventArgs e)
    {
        // Here you can access the standard page
        StandardPage standardPage = e.Content;
    }
}

You can also specify if the Content that the event applies to needs to be the exact Content Type or that the class would inherit from it by overriding the boolean property AllowInheritance.

protected override bool AllowInheritance { get { return true; } }

Tests

I’m still learning how to best create tests with Episerver, so I have added a Test Project where I want to test if the events are bound and unbound properly.

I have also added some tests to make sure that I have not missed any interfaces or classes. The project is found in the same GitHub Repo.

You’re welcome!

I would really recommend that you take your time to extract the code for your events from the Content Types.
Just putting the ServiceConfiguration attribute on your Content Types would instantiate the class in a way that doesn’t always play well with Episerver.

I’m planning to update the NuGet feed with my new version! Keep your eyes open for updates in Visual Studio if you have used the previous version.

Leave a comment