November Happy Hour will be moved to Thursday December 5th.

Alexander Haneng
Aug 13, 2012
  32110
(1 votes)

How to create a simple Block Type in EPiServer CMS 7

In EPiServer 7 you can defined block types in code. In this blog post we cover how to create your first block type in this way.

 

Updated to EPiServer 7 CMS on 15.01.2013

This blog post was originally written for a preview version of EPiServer 7 CMS, but is now updated to the final release version.

 

What is a block type?

Just like we have page types and pages we have block types and blocks. But what are blocks, and what are they used for? Here is where it gets a little confusing, but hang in there.

 

Group of properties

Think of blocks as a group of properties. E.g. you have an image url and an image description. With blocks you can add an image url property and an image description property to a new block type and call it image.

 

image

Group the image property and image description property together in a block type image.

 

You can now add this new block just like any other type of property to a page type. You can even add it multiple times to the same page type (think Image1, Image2 etc.) and multiple page types (think ArticleImage on the article page type and  NewsImage on the news page type).

Just like page types has a page type template (.aspx), block types has a block type template user control (.ascx) that renders the properties the way you want.

 

Shared blocks

And now to the confusing part: all blocks are also “shared blocks”. So you can create a new block (just like you create a new page) of the block type and add it to a content area on a page (note: page, not page type). This is similar to EPiServer Composer blocks. Also once you create a block (note: block, not block type) you can reuse it on other pages. This is similar to EPiServer global blocks. (Note: You can prevent a block from being used as a “shared block” by setting the AvailableInEditMode attribute to false)

 

image

The shared blocks widget shows up in the right hand side bar. Here you can create new blocks just like you can create new pages.

 

image

The blocks you create can be dragged into content areas on pages.

 

Lets create a simple block type

A block type in EPiServer 7 consists of two parts:

1. A block type class (.cs) that defines what properties the block should contain

2. A block template (.ascx) that renders the block and those properties.

 

Creating a block type class

Here is a simple block type class that defines our block type MyBlock. (Bonus sound track: On My Block – Scarface)

 

MyBlock.cs

using System.ComponentModel.DataAnnotations;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAnnotations;
using EPiServer.Web;
 
namespace EPiServer.Templates.Alloy.Models.Blocks
{
    [ContentType(DisplayName = "MyBlock", Description = "")]
    public class MyBlock : BlockData
    {
 
       [UIHint(UIHint.Image)]
       [Display(
           Name = "Image Url",
           Description = "",
           GroupName = SystemTabNames.Content,
           Order = 1)]
       public virtual Url ImageUrl { get; set; }
 
 
       [Display(
           Name = "Image Description",
           Description = "",
           GroupName = SystemTabNames.Content,
           Order = 2)]
       public virtual string ImageDescription { get; set; }
    }
}

 

MyBlock has two properties: Image url that contains the URL to the image we want to show and image description that describes the image. (Here is a quick reference on how to define the other property types in EPiServer 7, like XhtmlString, LinkCollection and Number)

 

Creating a block template

To display our new block type we create a user control.

MyBlockTemplate.ascx

<%@ Control Language="C#" AutoEventWireup="true" 
    CodeBehind="MyBlockTemplate.ascx.cs" 
    Inherits="EPiServer.Templates.Alloy.Views.Blocks.MyBlockTemplate" %>
<EPiServer:Property PropertyName="ImageUrl" runat="server" /><br/>
<EPiServer:Property PropertyName="ImageDescription" runat="server" />

 

In the code behind for the .ascx file we set the connection between the block type class and the block template by setting BlockControlBase<MyBlock> (where MyBlock is our block type class.)

 

MyBlockTemplate.ascx.cs

using System;
using EPiServer.Templates.Alloy.Models.Blocks;
using EPiServer.Web;
 
namespace EPiServer.Templates.Alloy.Views.Blocks
{
    public partial class MyBlockTemplate : BlockControlBase<MyBlock>
    {
        protected void Page_Load(object sender, EventArgs e)
        {
 
        }
    }
}

 

 

Using our new block type as a “shared block”

After building the project and starting our EPiServer 7 site we can use the new block type as a “shared block”. You can view the new block type in admin mode (under the “Block Type” tab).

 

image

 

You can now create and publish a new “shared block” of the type MyBlock in edit mode. (Click the + button on the top bar and choose “New Block”)

 

image

 

 

Add the block you just created to the content area of a page. (You can try a “Standard Page” in the Alloy demo. Drag your block from the “Shared Block” widget into the content area.)

 

image

 

You can use the block you created on multiple pages, and if you change and publish the block, all the pages will show the updated block. Neat!

 

 

 

Using our new block type as a property on a page type

The great thing about block types are that we can add them as properties to page type just like the built in properties. Lets modify the MyPage page type we created in the blog post “How to create a simple Page Type in code for EPiServer CMS 7” to contain a MyBlock.

Add a MyBlock property named Image to the MyPage page type class:

 

MyPage.cs

using System.ComponentModel.DataAnnotations;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAnnotations;
using EPiServer.Templates.Alloy.Models.Blocks;
 
namespace EPiServer.Templates.Alloy.Models.Pages
{
    [ContentType(DisplayName = "MyPage")]
    public class MyPage : PageData
    {
        [Display(
            Name = "My name",
            Description = "",
            GroupName = SystemTabNames.Content,
            Order = 1)]
        public virtual string MyName { get; set; }
 
        [Display(
            Name = "Image",
            Description = "",
            GroupName = SystemTabNames.Content,
            Order = 2)]
        public virtual MyBlock Image { get; set; }
 
    }
}

 

 

Add a EPiServer:Property to the page type template. This will render our block type template user control.

MyPageTemplate.aspx

<%@ Page Language="c#" 
    Inherits="EPiServer.Templates.Alloy.Views.Pages.MyPageTemplate" 
    CodeBehind="MyPageTemplate.aspx.cs" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>My Page Template</title>
</head>
<body style="background-color: white;">
<form id="Form1" runat="server">
<div>
<h1>MyPage Template</h1>    
My name is
<EPiServer:Property runat="server" PropertyName="MyName" />
<br/><br/>
<EPiServer:Property runat="server" PropertyName="Image" />
</div>
</form>
</body>
</html>

 

After building the project and starting our EPiServer 7 site we can see the new MyBlock property on the MyPage type in admin mode.

image

 

When creating a new MyPage page we can edit our MyBlock properties.

 

image

 

If we click inside the green box the editor will open our MyBlock properties.

image

 

After we publish the page this is what the visitors will see:

image

 

That was how to create your first block type in EPiServer 7 from code.

Aug 13, 2012

Comments

Joel Abrahamsson
Joel Abrahamsson Aug 13, 2012 07:14 PM

Great post Alex! The only complaint I have is that I now have to revise the nine post series about blocks that I had in the makings ;)

Aug 13, 2012 11:00 PM

I am sure you have more interesting things to blog about ;-)

Sep 10, 2012 01:41 PM

Excellent post! Do you know if it's possible to allow for a Block to be shared only to certain pages/page types?

Sep 28, 2012 01:50 PM

Yeah great post! Blocks is really welcome.

seth@blendinteractive.com
seth@blendinteractive.com Jan 4, 2013 07:38 AM

In the released CMS 7 I ran into an issue when I used a string datatype on a PropertyImageUrl like that. The property wouldn't save until I changed it to a Url datatype.

Jan 15, 2013 03:32 PM

Seth: The code has now been updated to the final version of EPiServer 7.

Alexander Helsinghof
Alexander Helsinghof Apr 7, 2013 11:32 AM

I have a problem with creating a block:
The Projectname type cannot be used as type parameter 'T' in the generic type or method 'EPiServer.TemplatePage'. There is no implicit reference conversion from 'myproject.Blocks.ContactBlock' to 'EPiServer.Core.PageData'.

any ideas of this?
// Alexander

 ben.xinpei.guo@gmail.com
ben.xinpei.guo@gmail.com Apr 11, 2013 09:14 AM

I am trying to create a block type and template as what you said above.
After I create the block type "MyBlock.cs" and the template "MyblockTemplate.ascx", this block type does not shown in the admin or edit mode. So I tried to build the project in Visual Studio 2010, however, after I built the project, the site cannot be open now. The below error message is shown.

Anyone has any idea on this???
Thanks a lot ,

Ben



Server Error in '/' Application.

Connection string 'CmoEntities' is not found
Parameter name: name

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ArgumentException: Connection string 'CmoEntities' is not found
Parameter name: name

Source Error:


[No relevant source lines]

Source File: c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\7f2d109f\8499e8ac\App_global.asax.0.cs Line: 0

Stack Trace:


[ArgumentException: Connection string 'CmoEntities' is not found
Parameter name: name]
EPiServer.Cmo.Core.Entities.CmoDataBase..ctor(String name) +377
EPiServer.Cmo.Cms.CmoInitialization..ctor() +99

[TargetInvocationException: Exception has been thrown by the target of an invocation.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +159
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +256
System.Activator.CreateInstance(Type type, Boolean nonPublic) +127
System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) +14426381
System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) +200
System.Activator.CreateInstance(Type type, Object[] args) +38
System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +248
System.Linq.d__b1`1.MoveNext() +296
System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +536
System.Linq.Enumerable.ToList(IEnumerable`1 source) +80
EPiServer.Framework.Initialization.InitializationEngine.Initialize(HostType hostType) +99
EPiServer.Framework.Initialization.InitializationModule.Initialize(HostType hostType) +308
EPiServer.Framework.Initialization.InitializationModule.FrameworkInitialization(HostType hostType) +93
EPiServer.Global..ctor() +102
EPiServer.Templates.Alloy.Global..ctor() +40
ASP.global_asax..ctor() in c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\7f2d109f\8499e8ac\App_global.asax.0.cs:0

[TargetInvocationException: Exception has been thrown by the target of an invocation.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +159
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +256
System.Activator.CreateInstance(Type type, Boolean nonPublic) +127
System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) +14426381
System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) +200
System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture) +28
System.Web.HttpRuntime.CreateNonPublicInstance(Type type, Object[] args) +83
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +312
System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +475

[HttpException (0x80004005): Exception has been thrown by the target of an invocation.]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +12880068
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +159
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +12721257

Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.18033

 ben.xinpei.guo@gmail.com
ben.xinpei.guo@gmail.com Apr 11, 2013 09:14 AM

I am trying to create a block type and template as what you said above.
After I create the block type "MyBlock.cs" and the template "MyblockTemplate.ascx", this block type does not shown in the admin or edit mode. So I tried to build the project in Visual Studio 2010, however, after I built the project, the site cannot be open now. The below error message is shown.

Anyone has any idea on this???
Thanks a lot ,

Ben



Server Error in '/' Application.

Connection string 'CmoEntities' is not found
Parameter name: name

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ArgumentException: Connection string 'CmoEntities' is not found
Parameter name: name

Source Error:


[No relevant source lines]

Source File: c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\7f2d109f\8499e8ac\App_global.asax.0.cs Line: 0

Stack Trace:


[ArgumentException: Connection string 'CmoEntities' is not found
Parameter name: name]
EPiServer.Cmo.Core.Entities.CmoDataBase..ctor(String name) +377
EPiServer.Cmo.Cms.CmoInitialization..ctor() +99

[TargetInvocationException: Exception has been thrown by the target of an invocation.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +159
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +256
System.Activator.CreateInstance(Type type, Boolean nonPublic) +127
System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) +14426381
System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) +200
System.Activator.CreateInstance(Type type, Object[] args) +38
System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +248
System.Linq.d__b1`1.MoveNext() +296
System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +536
System.Linq.Enumerable.ToList(IEnumerable`1 source) +80
EPiServer.Framework.Initialization.InitializationEngine.Initialize(HostType hostType) +99
EPiServer.Framework.Initialization.InitializationModule.Initialize(HostType hostType) +308
EPiServer.Framework.Initialization.InitializationModule.FrameworkInitialization(HostType hostType) +93
EPiServer.Global..ctor() +102
EPiServer.Templates.Alloy.Global..ctor() +40
ASP.global_asax..ctor() in c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\7f2d109f\8499e8ac\App_global.asax.0.cs:0

[TargetInvocationException: Exception has been thrown by the target of an invocation.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +159
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +256
System.Activator.CreateInstance(Type type, Boolean nonPublic) +127
System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) +14426381
System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) +200
System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture) +28
System.Web.HttpRuntime.CreateNonPublicInstance(Type type, Object[] args) +83
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +312
System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +475

[HttpException (0x80004005): Exception has been thrown by the target of an invocation.]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +12880068
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +159
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +12721257

Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.18033

Per Lundkvist
Per Lundkvist Mar 26, 2014 10:35 AM

Great post, thanks!

oscar olsson
oscar olsson Jun 3, 2014 03:26 PM

Great post about block type, thanks!

Please login to comment.
Latest blogs
Optimizely SaaS CMS + Coveo Search Page

Short on time but need a listing feature with filters, pagination, and sorting? Create a fully functional Coveo-powered search page driven by data...

Damian Smutek | Nov 21, 2024 | Syndicated blog

Optimizely SaaS CMS DAM Picker (Interim)

Simplify your Optimizely SaaS CMS workflow with the Interim DAM Picker Chrome extension. Seamlessly integrate your DAM system, streamlining asset...

Andy Blyth | Nov 21, 2024 | Syndicated blog

Optimizely CMS Roadmap

Explore Optimizely CMS's latest roadmap, packed with developer-focused updates. From SaaS speed to Visual Builder enhancements, developer tooling...

Andy Blyth | Nov 21, 2024 | Syndicated blog

Set Default Culture in Optimizely CMS 12

Take control over culture-specific operations like date and time formatting.

Tomas Hensrud Gulla | Nov 15, 2024 | Syndicated blog

I'm running Optimizely CMS on .NET 9!

It works 🎉

Tomas Hensrud Gulla | Nov 12, 2024 | Syndicated blog

Recraft's image generation with AI-Assistant for Optimizely

Recraft V3 model is outperforming all other models in the image generation space and we are happy to share: Recraft's new model is now available fo...

Luc Gosso (MVP) | Nov 8, 2024 | Syndicated blog