Create a Content Type
Why create a content type
Section titled “Why create a content type”Content types define the structure of your content. Every page, block, and media item in CMS is an instance of a content type. When your site needs a new kind of content — a product page, an event listing, a testimonial — you create a new content type.
What you will do
Section titled “What you will do”- Create a C# class that inherits from
PageData,BlockData, orMediaData - Add the
[ContentType]attribute with a display name and GUID - Add properties with display attributes
- Build and verify the type appears in the CMS editor
Create a page type
Section titled “Create a page type”using EPiServer.Core;
using EPiServer.DataAnnotations;
using System.ComponentModel.DataAnnotations;
namespace MySite.Models
{
[ContentType(
DisplayName = "Event Page",
GUID = "d1e2f3a4-b5c6-7890-abcd-ef1234567890",
Description = "A page for upcoming events",
GroupName = "Specialized")]
[AvailableContentTypes(Include = new[] { typeof(EventPage) })]
public class EventPage : PageData
{
[Display(Name = "Event Name", Order = 10)]
[Required]
public virtual string EventName { get; set; }
[Display(Name = "Event Date", Order = 20)]
[Required]
public virtual DateTime EventDate { get; set; }
[Display(Name = "Location", Order = 30)]
public virtual string Location { get; set; }
[Display(Name = "Description", Order = 40)]
public virtual XhtmlString Description { get; set; }
[Display(Name = "Registration Link", Order = 50)]
public virtual Url RegistrationLink { get; set; }
}
} Key decisions:
- GUID — Must be unique and never change after deployment. Generate one using
Guid.NewGuid()or an online tool. - GroupName — Controls where the type appears in the “New page” dialog. Common groups:
Content,Specialized,Containers. - AvailableContentTypes — Restricts which child page types can be created under this type.
Create a block type
Section titled “Create a block type”using EPiServer.Core;
using EPiServer.DataAnnotations;
using System.ComponentModel.DataAnnotations;
namespace MySite.Models
{
[ContentType(
DisplayName = "Testimonial",
GUID = "e2f3a4b5-c6d7-8901-bcde-f23456789012",
Description = "A customer testimonial with quote and attribution")]
public class TestimonialBlock : BlockData
{
[Display(Name = "Quote", Order = 10)]
[Required]
public virtual string Quote { get; set; }
[Display(Name = "Author Name", Order = 20)]
public virtual string AuthorName { get; set; }
[Display(Name = "Author Title", Order = 30)]
public virtual string AuthorTitle { get; set; }
[Display(Name = "Author Photo", Order = 40)]
public virtual ContentReference AuthorPhoto { get; set; }
}
} Blocks inherit from BlockData instead of PageData. They do not have URLs — they are embedded within pages via ContentArea properties.
Verify in the editor
Section titled “Verify in the editor”After building your project:
- Navigate to the CMS editor
- Right-click in the content tree and select “New page”
- Your new type should appear in the list, grouped by
GroupName - Create an instance and verify all properties appear in the editing form
Common issues
Section titled “Common issues”| Issue | Cause | Fix |
|---|---|---|
| Type does not appear in editor | Missing [ContentType] attribute | Ensure the attribute is present with a valid GUID |
| Properties not showing | Missing [Display] attribute | Add [Display] with Name and Order |
| Build error on property | Property not virtual | All CMS properties must be virtual |
| Duplicate GUID error | Same GUID used on two types | Generate a new unique GUID |
1. You created a new content type class, but it does not appear in the 'New page' dialog in the CMS editor. The project builds successfully. What is the most likely cause?
Without the [ContentType] attribute and a valid GUID, the CMS does not register the class as a content type, so it will not appear in the editor. This is the most common cause when the project builds but the type is missing.
Without the [ContentType] attribute and a valid GUID, the CMS does not register the class as a content type, so it will not appear in the editor. This is the most common cause when the project builds but the type is missing.
Review this topic →2. You need to create a customer testimonial that will be embedded within other pages, not accessed by its own URL. Which base class should your content type inherit from?
BlockData is the correct base class for reusable content that gets embedded within pages via ContentArea properties. Unlike PageData, blocks do not have their own URLs — they exist as components within pages.
BlockData is the correct base class for reusable content that gets embedded within pages via ContentArea properties. Unlike PageData, blocks do not have their own URLs — they exist as components within pages.
Review this topic →3. You are defining a content type and need to ensure editors can only create specific child page types underneath it. Which attribute controls this restriction?
The [AvailableContentTypes] attribute with the Include parameter restricts which child page types can be created under a given content type, enforcing content hierarchy rules.
The [AvailableContentTypes] attribute with the Include parameter restricts which child page types can be created under a given content type, enforcing content hierarchy rules.
Review this topic →