How You Can Make Use Of Local Blocks To Write Less Code and Standardize The CMS

One very common requirement on every project is to create a number of page and blocks with either an image or link the content editor adds.  In Episerver when we do this we use a ContentReference to get a reference to the asset and then somewhere before the page is rendered we use the Episerver API to translate the content reference id into a friendly Url.

As good developers, one of the architectural goals we want to follow is DRY (don't repeat yourself), e.g. avoid writing unneeded/duplicate code.  In today's post, I'm going to explain how we can structure Episerver to avoid breaking the DRY principle when it comes to these common datatypes.

What Are These Common Datatypes

 The most common examples of these common sets of properties are:

  • An image (URL and Alt text)
  • Responsive Image (desktop URL, mobile URL, alt text)
  • Buttons/CTA (button text, button URL)
  • Link (URL, title, link text)

Depending on your design, you will likely bump onto other examples, maybe HTML components etc..  My advice when you start building your website is to think of a nice and clean way to deal with this, keep reading to learn how

Interface Or Block

The main two approaches to deal with this duplication is to either create an interface for each type or, to create a noneditable local block.  

The Interface Approach

For each of these common types you create an interface and them implement that interface where needed, e.g.:

public interface IImageProperties
{
      ContentReference Url { get; set; }
      
      string AltText { get; set; }
}

In your controller/view model, you can then create a common helper method that converts the interface to the end data required, e.g.

public ImageViewModel PopulateData(IImageProperties imageProperties)
{
  return new ImageViewModel
  {
    FriendlyUrl = GetFriendlyUrl(imageProperties.Url)
    AltText = imageProperties.AltText
  };
}

This approach works semi-well, it's definitely a lot better than manually writing the same properties over and over again. The downside is that you can only add a type onto each page/block. You also have to write all the property set-up code each time. The properties also don't group as nicely in the editor.

For these reasons, I tend to use the local read-only block approach, which I'll cover next.

Local Readonly Blocks

The local read-only block option is pretty similar to the interface approach. Instead of using an interface we create a local block, however, we set the appropriate attribute on these blocks so they are hidden from content editors and they can only be used specifically by developers on the pages/blocks when needed.  An example of the same image example can be seen below:

 [ContentType(
        GUID = "c81b9c9b-553d-46b6-8ec5-4d7f9fe33acb",
        DisplayName = "Image",
        AvailableInEditMode = false)]
    public class ImageBlock : BlockData
    {
        [Display(
            Name = "Url",
            Description = "Url.",
            GroupName = SystemTabNames.Content,
            Order = 10)]
        [UIHint(UIHint.Image)]
        public virtual ContentReference Url { get; set; }

        [CultureSpecific]
        [Display(
            Name = "Alt Text",
            Description = "Alt Text.",
            GroupName = SystemTabNames.Content,
            Order = 20)]
        public virtual string AltText { get; set; }
    }

You can then use the block in your pages/block in a local block, like so:

 
   [ContentType(
        DisplayName = "MyBlock")]
    public class MyBlock : BlockData
    {
        [Display(
            Name = "Image",
            Description = "Image.",
            GroupName = SystemTabNames.Content,
            Order = 10)]
        [UIHint(UIHint.Block)]
        public virtual ImageBlock Image { get; set; }
    }

When you think about tackling this duplication, local blocks is the approach I'd recommend.  To make the block hidden from editors note the AvailableInEditMode = false.  Using this approach will mean your related properties will be grouped in the CMS, you can minimise the amount of boilerplate property code you need to write and you'll end up having to write fewer unit tests, as you can create a generic method, like the one above to simplify your code.

Local Blocks Takeaway

When working with Episerver, every website will have common functionality like needing to display images and links.  Without a good technical approach, you'll end up writing a lot of duplicate code and test code every time one of these repeated types is required.  A better approach to tackle the situation is to group all related functions together as local blocks that are hidden from the content editor.  You can then use these blocks as local blocks and make your life a lot easier.  

submit to reddit

Jon D Jones

Software Architect, Programmer and Technologist Jon Jones is founder and CEO of London-based tech firm Digital Prompt. He has been working in the field for nearly a decade, specializing in new technologies and technical solution research in the web business. A passionate blogger by heart , speaker & consultant from England.. always on the hunt for the next challenge

Back to top