London Dev Meetup Rescheduled! Due to unavoidable reasons, the event has been moved to 21st May. Speakers remain the same—any changes will be communicated. Seats are limited—register here to secure your spot!

How to handle inheritance in the Conventions API?

Vote:
 

I'm looking for guidance on the proper way to define conventions in the Conventions API when working with an abstract base class and its derived content types.

In my project, I have an abstract base class PageBase where I’ve defined some shared field exclusions and inclusions like this:

conventionRepository
    .IncludeAbstract<PageBase>()
    .ForInstancesOf<PageBase>()
    .ExcludeField(p => p.MetaTitle)
    .ExcludeField(p => p.MetaDescription)
    .IncludeField(p => p.MetaTitleWithFallback())
    .IncludeField(p => p.MetaDescriptionWithFallback());

Then for a concrete type like ArticlePage (which inherits from PageBase), I have:

conventionRepository
    .ForInstancesOf<ArticlePage>()
  .Set(p => p.BlockArea, IndexingType.OnlyStored)
    .Set(p => p.MainBody, IndexingType.OnlyStored);

Problem:
When I index the content, the PageBase type is recognized in the Graph index, but ArticlePage is omitted entirely. However, if I comment out the ArticlePage-specific conventions and re-index, ArticlePage appears as expected.

Is there a correct pattern or approach to layering conventions for inherited types like this? Am I unintentionally overriding something by defining both?

Any insights or examples would be greatly appreciated!

#337827
Edited, Apr 15, 2025 13:58
Vote:
 

I've been trying to do the same thing using interfaces by setting ForInstancesOf<> for Interface1 and Interface2. After that, I ran into an issue with a GenericPage type that implements both interfaces. It turns out that a content type can't have more than one convention registered. In my case, GenericPage matched two conventions. It looks like your ArticlePage is also matching both the PageBase convention and the one for ArticlePage.
From what I can tell, this happens because the convention repository uses .SingleOrDefault<ConventionType>() when resolving a convention, so only one match is allowed.

What worked for me was creating a custom extension method that applies shared settings. In your case, it could look something like this (pseudo-code):


internal static ConventionType<T>? SetPageBaseConvention<T>(this ConventionType<T>? conventionType) where T : PageBase =>
    conventionType
        ?.ExcludeField(p => p.MetaTitle)
        .ExcludeField(p => p.MetaDescription)
        .IncludeField(p => p.MetaTitleWithFallback())
        .IncludeField(p => p.MetaDescriptionWithFallback());

and then:


conventionRepository
    .IncludeAbstract<PageBase>();

conventionRepository
    .ForInstancesOf<ArticlePage>()
    .SetPageBaseConvention<ArticlePage>()
    .Set(p => p.BlockArea, IndexingType.OnlyStored)
    .Set(p => p.MainBody, IndexingType.OnlyStored);

Although it works pretty well for me, I can see this approach could not be optimal for base abstract classes as it would require doing SetPageBaseConvention<> for each child content type. 

 

#337840
Edited, Apr 16, 2025 6:44
Vote:
 

Thank you very much for the helpful explanation and the suggested workaround!

Your insight about only one convention being applied due to SingleOrDefault<ConventionType>() makes a lot of sense — that explains the behavior I was seeing.

One additional requirement I have is the ability to query pages based on their base type and still access the shared fields without needing to know the exact derived type at query time. That’s why I was initially hoping to define conventions at the base class level and have them inherited automatically.

After some more testing, I found another approach that seems to work for my use case: I decorated the relevant properties in the derived types with the [GraphProperty(PropertyIndexingMode.OutputOnly)] attribute. It probably has some limitations in certain scenarios, but for now, it seems to strike the right balance for what I need.

Appreciate your input — it helped clarify the underlying mechanics of how conventions are resolved!

#337863
Apr 16, 2025 12:55
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.