Linus Ekström
Apr 10, 2014
visibility 4950
star star star star star
(2 votes)

Property Renderers and nullable types

Today I got a question from a collegue that could not get a specific property template for a DateTime property to be used. The template resolver never selected this renderer for some reason, even if the tags was matching. Since I’ve seen other people having the same issue I thought I’d give a short description to what the problem is and also how to fix it.

The property declaration in the model looked like this:

public virtual DateTime OriginallyPublished { get; set; }

And the property template like this:

[TemplateDescriptor(TagString = "ArticleDate", TemplateTypeCategory = TemplateTypeCategories.ServerControl)]
    public partial class ArticleDate : PropertyControlBase<DateTime>
    {
        protected override void CreateChildControls()
        {
            Controls.Add(new Label() { Text = "Just some text to test" });
        }
    }

The usage on the template looked like this:

<EPiServer:Property PropertyName="OriginallyPublished" CustomTagName="div" runat="server">
    <RenderSettings Tag="ArticleDate" />
</EPiServer:Property>

Now given the theory how templates are selected given the type and tags, one could think that the ArticleDate class would be selected since the property is of type DateTime and the Tags defined for rendering matches the TagString on the TemplateDescriptor. Still, this template is not selected. Why then is that the case?

Nullable properties

The answer is that EPiServer stores some simple value types as a nullable type, for instance Nullable<DateTime>. We still allow model declarations being non-nullable, setting the default value for the type if the backing value is null. However, when matching value type with templates, we use the internall data type. So the quick fix is simply to add nullable to your template:

public partial class ArticleDate : PropertyControlBase<Nullable<DateTime>>

I have reported a bug to see if we can handle this oddity in a transparant way so that you don’t have to care about this as a site developer.

Apr 10, 2014

Comments

error Please login to comment.
Latest blogs
Extending a Contract: What You Can Override

Contracts share fields across content types — but not every field setting can be overridden. Push the same contract onto several components, and CM...

Chirag Khanna | Sep 18, 2026 |

Building a Blazor Server UI Inside the Optimizely CMS 13 Admin Shell

What I learned shipping a Blazor Server UI inside Optimizely CMS 13 — Razor components in a NuGet package, the Blazor hub next to MapContent(),...

Stanisław Szołkowski | Sep 17, 2026 |

Giving Optimizely 13 Content Types Meaningful Icons and Thumbnails

When working with an Optimizely CMS solution that has evolved over time, it is common to end up with many content types. As the number grows, the...

Pär Wissmark | Sep 16, 2026 |

force-dynamic vs connection() for Optimizely Graph

If you have built an Optimizely CMS SDK site, you already know getContentByPath on a catch-all. This post is about the part that file never says ou...

Chirag Khanna | Sep 16, 2026 |

I built a thing - nOSC & nOCP - an experiment?

I don't think I'm always that convensional . And that's where this starts... So firstly, I was lucky enough to see OCP UI extensions for Optimizey...

Matt Pallatt | Sep 15, 2026

A day in the life of an Optimizely OMVP: OptiA11y: accessibility help for Optimizely editors that refuses to lie to them

Most accessibility tooling in the CMS space has the same shape. A crawler walks your published site, renders each page, runs axe-core over the DOM,...

Graham Carr | Sep 15, 2026