Orchard CMSAdding Content Parts to Content Types

I just learned an important Orchard feature. Jotting it down here while it’s still fresh.

First, a brief background. Orchard CMS spits pages out as Content Types. Any Content Type can end up being a web endpoint, or “slug”. Content Types are made up of Content Parts, which are bits and pieces of content definition.

In Orchard, there are three ways to attach a Content Part to a Content Type.

1.) Via the Content Definition Menu

Navigate to Content Definition, then edit the Content Type. From there, you can add different content parts that have already been defined.

2.) Via Migrations

For Developers and Custom Module Builders, you can create a Migrations.cs file with a class that implements the DataMigrationImpl interface. Using the Create() and UpdateFromX methods, you can manually define Content Parts and Content Definitions as well as wiring up the database structures necessary to hold your custom module’s content.

There are two key methods to use when tweaking Part Definitions and Part Types:

  • ContentDefinitionManager.AlterTypeDefintion
  • ContentDefinitionManager.AlterPartDefinition

There are tons of examples in the Orchard code for how to do this, so I won’t delve into it.

3.) Via the ActivatingFilter

The problem with the first two methods is that it will let Orchard Admins remove your Content Part from the Content Type you attached it to. If you have code that expects a certain Content Part to always be attached to a certain Content Type, then the ActivatingFilter is your solution.

Filters are wired up in the Content Handler. There is a decent write-up here: [Orchard Content Handler]( "Orchard Content Handlers")s

In a nutshell, if you need to ALWAYS have a Content Part attached to a particular Content Type, then use the ActivatingFilter. A good example of this would be some content part you wanted to add to the Site Settings Content Type. Your code would look something like this. Take a look at the ActivatingFilter call. The value in the angle braces if the Content Part you want to attack, and the value in quotes is the Content Type that you want to attach the part to. So the below code is attaching the CacheSettings to the Site Settings menu.

namespace Orchard.OutputCache.Handlers {
    public class CacheSettingsPartHandler : ContentHandler {
        private readonly ICacheService _cacheService;

        public CacheSettingsPartHandler(
            IRepository<CacheSettingsPartRecord> repository,
            ICacheService cacheService) {
            _cacheService = cacheService;
            Filters.Add(new ActivatingFilter<CacheSettingsPart>("Site"));

            // initializing default cache settings values
            OnInitializing<CacheSettingsPart>((context, part) => { part.DefaultCacheDuration = 300; });

            // evict modified routable content when updated
            OnPublished<IContent>((context, part) => Invalidate(part));