Episerver + AutoMapper is a confusing combo

Published on in C# and Episerver

Blocks in Episerver implement the IContent interface only during runtime which makes using AutoMapper difficult.

A few weeks ago I started using AutoMapper in an Episerver (.NET CMS) project to map models to view models semi-automatically.

My initial feelings: 😻

It was quite nice until I started creating mappings for blocks (reusable pieces of content).

My feelings now: 😿😾

Whereas page models implement Episerver's IContent interface "normally," block models implement the IContent interface only during runtime.

This means that creating a mapping from IContent to a block type is not possible. At least not possible in this way that I tried:

// Base view model for pages and blocks
public interface IContentViewModel
{
    string ContentLink { get; set; }
    string ContentType { get; set; }
    // etc.
}

public class IContentProfile : Profile
{
    public IContentProfile()
    {
        CreateMap<IContent, IContentViewModel>();
    }
}

public class MyPageViewModel : IContentViewModel
{
    // ...
}

public class MyPageProfile : Profile
{
    public MyPageProfile()
    {
        CreateMap<MyPage, MyPageViewModel>()

            // `MyPage` implements `IContent`, so this is ok:
            .IncludeBase<IContent, IContentViewModel>();
    }
}

public class MyBlockViewModel : IContentViewModel
{
    // ...
}

public class MyBlockProfile : Profile
{
    public MyBlockProfile()
    {
        CreateMap<MyBlock, MyBlockViewModel>()

            // Error! `MyBlock` doesn't implement `IContent` until runtime,
            // so this doesn't work:
            .IncludeBase<IContent, IContentViewModel>();
    }
}

I eventually came up with a solution, but it feels very complex and very verbose.

I don't know if AutoMapper should be this difficult. If you are working on an Episerver project, my suggestion would be to research alternative mappers or do mappings manually.