Content type mismatch exception in Optimizely

The TypeMismatchException exception came up recently after making some changes to namespaces and assemblies in an Optimizely project. This proved to be an interesting issue and I will explain my findings from investigating the problem — in the hopes that it will help another developer in the future.

The exception

As we can see in the exception below, there is a problem with a piece of content that does not inherit from the correct content type. The content is an image and it inherits from ImageData instead of the expectedImageFile type.

An unhandled exception occurred while processing the request.
TypeMismatchException: Content with id '1234' is of type 'EPiServer.Core.ImageData_DynamicProxy' which does not inherit required type 'MyProject.Models.Media.ImageFile'
EPiServer.Core.Internal.DefaultContentLoader.ThrowTypeMismatchException(ContentReference link, Type actual, Type required)

What's the problem?

The exception is caused by an invalid object cast. In my case I was casting image content to ImageFile, but the content had somehow changed to be of type ImageData. What is actually happening is that the custom content type is no longer recognized and the primary type is used as a fallback. The type does still exist in the solution, but it has been moved to a new assembly and namespace. The problem is that the content types in the new assembly are not picked up by the CMS.

Content type synchronization

On startup the assemblies of the application are automatically scanned for content types and then those types are synchronized to the database. Any of the referenced assemblies can also contain content types and will be synchronized in the same way. It's interesting to note that this only works for assemblies with a dependency to the EPiServer.Framework package. Besides that it also does not seem to work for assemblies that are added to the project as a direct DLL reference.

How to fix it

The new assembly that contains the content type was added to the project as a direct DLL reference. This assembly was not being picked up by the AssemblyScanner during startup and therefore the content type was not synchronized correctly — like I described in the section above. In order to solve this issue I had to reference the assembly in a different way and opted for a private nuget package. Another way is to add a reference to the project instead of to the DLL directly.

Conclusion

The issue turned out to be caused by something quite different than I originally expected. It was interesting to learn about how the content type synchronization works in Optimizely. I doubt many people will encounter the same issue, because it's really an unlucky edge case with assembly referencing specific to my architecture. Although if anyone finds themselves in a similar situation then hopefully this post will help them.