TOP 10 Episerver CMS 10 Changes for Developers

First of all, Episerver 10 is backward compatible 99.9% but in upgrade you should be aware of few things! Here is my top 10 list of CMS changes:

1 Add-ons EPiServer.CMS.Core All add-ons are not yet updated to support new major version.
2 CMS-2295 EPiServer.CMS.UI Remove support for legacy dot syntax for dojo modules
3 CMS-3812 EPiServer.CMS.Core Confusing handling of empty/null properties
4 CMS-1449 EPiServer.CMS.Core Date/time should be stored in UTC by default
5 CMS-4167 EPiServer.CMS.Core Change ContentCoreData StartPublish and StopPublish to DateTime?
6 CMS-1380 EPiServer.CMS.UI Move EPiServer.Shell from EPiServer.CMS.Core to EPiServer.CMS.UI.Core
7 CMS-4149 EPiServer.CMS.Core Remove support for legacy value types for PropertyData
8 CMS-4110 EPiServer.CMS.Core MovingContent and MovedContent isn’t different when removing a content
9 CMS-3991 EPiServer.CMS.Core PermanentLinkMapper API is hard to understand/use
10 CMS-3290 EPiServer.CMS.Core Make LinkItem members virtual to simplify unit testing


Working with Responsive Design Projects

Working as a software architect in projects where visual appearance, user interfaces and large scale of device support is as important as the right data and the functioning is very different than being just a back-end developer in a project where the UI just need to work with couple of different devices. It requires a lot more consideration of different kind of needs and point of views. It often requires some understanding and co-operation of:


CSV Table Block Concept for Episerver

This is an option to avoid usage tables in WYSIWYG HTML editor. Tables in any rich text editor have always be problematic for responsive design, but data often exists in table format (example in Excel) so the usage of table tools is inevitable.

We are using CSV (comma separated values) as description of table because almost all systems and software (example Excel) can produce CSV data. Also because CSV is readable and editable for much larger group of people than example XML or JSON. PropertyList would be one good option to improve the editor’s experience but in this case the data came mostly from external sources. So the import feature was much more important.

CSV Table Block Example

(unfortunately, screenshots and URL examples are only in Finnish)

You can find live example of table block in Evira’s web page.

csv table block


Scheduled Job Manager for cleaning Episerver background tasks


Episerver scheduled job manager for cleaning and maintaining scheduled jobs. Sometimes you may find old scheduled jobs in database if the scheduled job is renamed, moved or deleted. Old Scheduled jobs are not automatically deleted but with this tool you can easily and safely delete those useless scheduled jobs.

This is basically single file solution for developers and administrators which you can drop into any environment and start using it without any maintenance breaks (no application pool recycle).

Source codes can be found in github:


No parameterless constructor exception, Greediest Constructor and DefaultConstructor-attribute

You propably have pump into IoC framework (StructureMap) problem “No parameterless constructor” but are you familiar with StructureMap constructor selection, greediest constructor rule, default constructor attribute and good practices of implementing multiple constructors.

You probably have seen this YSOD-screen before and it actually says that my StartPageController-does not have parameterless constructor.  In this case the original problem had happen way before this MissingMethodException was thrown. The original exception was catch and written down into log-file and it hides the original exception. That’s definitely a problem but in this case there was a good reason for it and it’s not the original problem.

No parameterless constructor

Log file tells that something has broke the StructureMap and that’s why none of the future StructureMap requests can be processed.

In this case the problem was simple “Required primitive dependency is not explicitly defined“. So there was string parameter in the constructor which StructureMap try to use. StructureMap selects the constructor which had the most parameters (Greediest Constructor -rule).

One simple solution to primitive type constructor parameter is to mark constructor with DefaultConstructor-attribute and initial the default values in runtime. Note that the other constructor has it’s own purpose also.

This way your you don’t have to mind what type of constructor parameter you have and you don’t have to define constructor and default values in your StructureMap configuration method.


Elasticsearch NEST 2 Upgrade Cheat Sheet (version 1.7 -> 2.0)

NEST version 2 official documentations:

NEST 1.7
NEST 2.0
 .Types(new[] {
  string.Join(“,” ,
     new[] {
     }.Select(t => t.Name.ToLower())
.SortAscending(o => o. Time)
.Sort(sd => sd.Ascending(o => o. Time))
.Search<T>(s => s
   .Filter(m => m
      .Term(t => t.Field(f => f.TypeId).Value(5)))
Direct conversion:
.Search<T>(s => s
   .PostFilter(m => m
      .Term(t => t.Field(f => f.TypeId).Value(5)))
In most cases is better to use Query level filters:
.Search<T>(s => s
   .Query(q => q
      .Bool(b => b
         .Filter(m => m
            .Term(t => t.Field(o => o.TypeId).Value(5))
KeyValuePair<string, Highlight>
.Highlights.FirstOrDefault(kvp => kvp.Key == “name” )
.PutIndexTemplate( EsSettings .IndexNameBase + “-template” , t => t
  .Template(EsSettings.IndexNameBase + “*”)
  .Settings(s => s
     .Add( “index.number_of_shards” , 1)
     .Add( “index.number_of_replicas” , 0)
  . AddMapping <_default_ >(ms => ms.Dynamic (DynamicMappingOption.Ignore))
.PutIndexTemplate(“my-index-template” , t => t
  .Settings(s => s
  .Mappings(mds => mds.Map< _default_>(s => s.Dynamic(DynamicMapping.Ignore)))
.Suggest(s => s.Term())
  .OnFieldsWithBoost (d => d
     .Add (entry => entry.Name , 2)
  .Fields(pf => pf
     .Field(entry => entry.Name, 2)
 .ScriptScore(sc => sc.Script (SearchScoreScript))
.Functions(sc => sc.ScriptScore(sf => sf.Script(f => f.Inline(SearchScoreScript))))
.Query(qc => qc.QueryString(q => q.Query($”{query}*”)))
.AliasExists(s => s.Index(aliasName)).Exists
.CreateIndex(id => id.Index(“index_name” ))
.CreateIndex( “index_name”, id => id)
[ElasticProperty(Type = FieldType.String, Index = FieldIndexOption .NotAnalyzed)]
[ElasticProperty(Type = FieldType.Object)]
[ElasticProperty(Type = FieldType.Nested)]
[StringAttribute(Index = FieldIndexOption .NotAnalyzed)]
NEST supports DeleteByQuery() OOTB, but elastic search requires Delete By Query -pluginSo the way to do it is with separate requests:
var deletedObjects =  elasticClient.Search<ObjectType>(i => i
   .Query(f => f.Term(e => e.ContentId, contentId))
var deleteResults = deletedObjects .Hits.Select(h =>
     elasticClient.Delete(new DocumentPath<object>(h.Id).Type(h.Type), s => s)
.Filter(f => f.Terms(o => o. ContentId, items))
.Filter(f => f.Terms(t => t.Field(o => o.ContentId).Terms(items)))


EPiServer Content Area Renderer With Row Support

EPiServer Display options is a really nice feature but it’s lacking a row rendering option for Bootstrap Grid system.


Without row-elements your grid will got broken quite easily and you need to create “dirty CSS hacks” to fix it.


To create rich content with various types of blocks and content sizes you need to separate the rows with <div class=”row”> -element.


Luckily EPiServer is so extendable that you can add the feature quite easily in your own project. So after adding the following codes you are able to get these rows and your HMTL is properly formatted for Bootstrap grid or some other grid system.



Adding rows in content area renderer is actually pretty simple job. You can make it much more fail safe and improved but this is the simple version.

    public class ContentAreaRendererWithRows : ContentAreaRenderer
	    // Wraps every 12 cells with row divs if the tags are used.
        protected override void RenderContentAreaItems(HtmlHelper htmlHelper, IEnumerable contentAreaItems)
            var items = contentAreaItems.ToArray();
            int rowWidthState = 0;
            var itemInfos = items.Select(item =>
                var tag = GetContentAreaItemTemplateTag(htmlHelper, item);
                var columnWidth = GetColumnWidth(tag);
                rowWidthState += columnWidth;
                return new
                    ContentAreaItem = item,
                    Tag = tag,
                    ColumnWidth = columnWidth,
                    RowWidthState = rowWidthState,
                    RowNumber = rowWidthState % 12 == 0 ? rowWidthState/12 - 1 : rowWidthState / 12,
            //if tags exists wrap items with row or not then use the deafault rendering.
            bool tagExists = itemInfos.Any(ii => !string.IsNullOrEmpty(ii.Tag));
                base.RenderContentAreaItems(htmlHelper, items);

            var rows = itemInfos.GroupBy(a => a.RowNumber, a => a.ContentAreaItem);
            foreach (var row in rows)
                htmlHelper.ViewContext.Writer.Write("<div class=\"row row"+row.Key+"\">");
                base.RenderContentAreaItems(htmlHelper, row);
        public static int GetColumnWidth(string tag)
            switch (tag)
                case Settings.ContentAreaTags.FullWidth:
                    return 12;
                case Settings.ContentAreaTags.TwoThirdsWidth:
                    return 8;
                case Settings.ContentAreaTags.HalfWidth:
                    return 6;
                case Settings.ContentAreaTags.OneThirdWidth:
                    return 4;
                    return 12;

        protected override string GetContentAreaItemCssClass(HtmlHelper htmlHelper, ContentAreaItem contentAreaItem)
            var tag = GetContentAreaItemTemplateTag(htmlHelper, contentAreaItem);
            return string.Format("block {0} {1}", GetTypeSpecificCssClasses(contentAreaItem, ContentRepository), tag);

        private static string GetTypeSpecificCssClasses(ContentAreaItem contentAreaItem, IContentRepository contentRepository)
            var content = contentAreaItem.GetContent(contentRepository);
            var cssClass = content == null ? String.Empty : content.GetOriginalType().Name.ToLowerInvariant();
            return cssClass;


    public class StructureMapConfig
        public static void ConfigureContainer(IContainer container)
            container.Configure(x =>


    public static class Settings
        public static class ContentAreaTags
            public const string FullWidth = "col-sm-12";
            public const string TwoThirdsWidth = "col-sm-8";
            public const string HalfWidth = "col-sm-6";
            public const string OneThirdWidth = "col-sm-4";


And Bob’s your uncle!!!