Using Interfaces to get more compatible content elements in Episerver

Interfaces are more or less basic stuff in programming and in Episerver development. You probably have seen these guys (IThisAndThat, IEtc..) all over the reference solutions (AlloyDemoKit, Quicksilver, …). In this blogpost, I’ll be taking a concrete approach how to make one of the AlloyDemoKit’s content blocks more compatible with other content elements using an Interface.

So, first things first. What is an Interface? If you already know the answer skip this paragraph, if not, have a look at one of the Stack Overflow’s answer. There are also Zombies in there: What is the definition of interface in object oriented programming?

Interfacing the Slide Show Block

In AlloyDemoKit we have a Slide Show Block (CarouselBlock) which acts as a container for carousel items (CarouselItemBlock). You can drag and drop those items to it, and everything works.

What if you want to drag a page to it, or an image? At this point it isn’t possible since the CarouselBlock’s content area accepts only specific carousel items. If we want to add pages to to it, we could simply add SitePageData as a AllowedContentType. However, the current code is expecting a predefined content properties and a CarouselItemBlock type. So that wouldn’t work.

The better and more robust way is to create a new Interface: ICarouselContent.

using EPiServer;
using EPiServer.Core;
using EPiServer.Shell;
namespace AlloyDemoKit.Business.Rendering
{
public interface ICarouselContent : IContentData
{
Url Image { get; set; }
string ImageDescription { get; set; }
string Heading { get; set; }
string SubHeading { get; set; }
string ButtonText { get; set; }
Url ButtonLink { get; set; }
bool Selected { get; set; }
}
[UIDescriptorRegistration]
public class CarouselContentDescriptor : UIDescriptor<ICarouselContent> { }
}

view raw
ICarouselContent.cs
hosted with ❤ by GitHub

What you see here is an interface extracted from the CarouselItemBlock class. There is also a UIDescriptor which is required to get the AllowedContentType attribute work (have a look at the Episerver documentation). We also want to add a reference to the interface in the CarouselItemBlock.cs.

public class CarouselItemBlock : SiteBlockData, ICarouselContent
//

view raw
CarouselItemBlock.cs
hosted with ❤ by GitHub

Next, we are going to make few changes to CarouselBlockController.cs, CarouselBlock.cs, CarouselViewModel.cs and CarouselItemBlock.cshtml

public class CarouselBlock : SiteBlockData
{
[Display(
GroupName = SystemTabNames.Content,
Order = 320)]
[AllowedTypes(new[] { typeof(ICarouselContent) })]
public virtual ContentArea MainContentArea { get; set; }
}

view raw
CarouselBlock.cs
hosted with ❤ by GitHub

//
var model = new CarouselViewModel
{
Items =
currentBlock.MainContentArea.FilteredItems.Select(
cai => contentLoader.Get<ICarouselContent>(cai.ContentLink)).ToList(),
CurrentBlock = currentBlock
};
//

@model AlloyDemoKit.Business.Rendering.ICarouselContent
// …

public class CarouselViewModel
{
public List<ICarouselContent> Items { get; set; }
public CarouselBlock CurrentBlock { get; set; }
}

view raw
CarouselViewModel.cs
hosted with ❤ by GitHub

What I did was, I simply replaced the references of the CarouselItemBlock to our newly created ICarouselContent Interface in all of the files.

At this point, everything should be in place. We have kept the original functionality, but we have created a new extension point. Now we can tell any content element that it should implement ICarouselContent interface.

By doing that and implementing required content properties, you can drag and drop the element to the CarouselBlock’s contentarea. Here is an example implementation for the SitePageData.

public abstract class SitePageData : PageData, ICustomCssInContentArea, ICarouselContent
{
//
[Display(GroupName = "CarouselContent", Order = 10)]
[CultureSpecific]
[UIHint(UIHint.Image)]
public virtual Url Image { get; set; }
[Display(GroupName = "CarouselContent", Order = 20)]
[CultureSpecific]
public virtual string ImageDescription
{
get
{
var propertyValue = this["ImageDescription"] as string;
return string.IsNullOrWhiteSpace(propertyValue) ? Heading : propertyValue;
}
set { this["ImageDescription"] = value; }
}
[Display(GroupName = "CarouselContent", Order = 30)]
[CultureSpecific]
public virtual string Heading { get; set; }
[Display(GroupName = "CarouselContent", Order = 40)]
[CultureSpecific]
[UIHint(UIHint.Textarea)]
public virtual string SubHeading { get; set; }
[Display(GroupName = "CarouselContent", Order = 50)]
[CultureSpecific]
public virtual string ButtonText { get; set; }
[Display(GroupName = "CarouselContent", Order = 60)]
[CultureSpecific]
public virtual Url ButtonLink { get; set; }
[Ignore]
public bool Selected { get; set; }
//
}

view raw
SitePageData.cs
hosted with ❤ by GitHub

You can now drag any page to the carousel that inherits SitePageData. If you want to drag images (or any other element), simply reference the ICarouselContent and implement it.

One thought on “Using Interfaces to get more compatible content elements in Episerver

Leave a Reply to Petri Isola Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.