OrchardCore: How to Backdate Blog Post

Posted by admin on May 01, 2023

I am a big fan of OrchardCore. Its architectural design is exactly what I want in a software system, and it allowed me to achieve exactly what I wanted with minimal code.

When I migrated this blog from a custom ASP.NET web app to OrchardCore, I was up and running with the Blog Recipe in mere minutes, if not seconds. Migrating the posts was easy because they were already written in markdown. But I did encounter one hiccup that took some effort to solve.

Problem

After I migrated all my existing blog posts, they all showed they were published on the same day, the day I set up my new OrchardCore site.

Root Cause

The default views provided by the blog recipe use the ContentItem.CreatedUtc date to display the published date. And the CreatedUtc is the created date of the content item, specifically a BlogPost content item.

But my posts we originally published months and years earlier, and I want my blog to display the original publication date.

Solution

As mentioned earlier, OrchardCore's design provides great flexibility in how content is captured and display. I used the built in extensibilty of OrchardCore to fix my publication date problem.

Extend the BlogPost ContentType

First, I added a new Publication Date field to the BlogPost content type definition.

  1. Log into the admin area of your OrchardCore site
  2. Navigate to Content->Content Definitions->Content Types and select the Blog Post to edit the content type
  3. Under the Fields section, click the Add Field button
  4. On the "Add new field" page, enter Publication Date for the Display Name and select Date Field (not DateTime!!) for the Field Type
  5. Then click Save
  6. On the Edit Content Type - Blog Post page, under the Fields section, click Edit next to your newly created Publication Date field

Now that you have a new Publication Date field, you can go to your existing blog posts and enter the original publication date for your blog post.

Override the BlogPost Display Templates

You now have a new PublicationDate field but the default templates that for BlogPost that come from the Blog recipe know nothing about this new field. You therefore need to override the templates to display this new field you added.

  1. Log into the admin area of your OrchardCore site
  2. Navigate to Content->Content Definitions->Content Types and select the Blog Post to edit the content type
  3. Look for a Edit templates button with a dropdown arrow at the top of the Edit Content Type - Blog Post page
  4. Click the Edit templates dropdown arrow and select the Template for Blog Post content item in detail views link
  5. This should navigate you to the Edit Template page where Name is Content__BlogPost and you can override the default Blog Recipe view by editing the Content section
  6. In the Content text area copy and past the following code
{% zone "Header" %}
    <!-- Page Header -->
    <!-- Set your background image for this header on the line below. -->
    {% assign imagePath = Model.ContentItem.Content.BlogPost.Image.Paths.first %}
    {% if imagePath == nil %}
        <header class="masthead" style="background-image: url('{{ "~/TheBlogTheme/assets/img/post-bg.jpg" | href }}')">
    {% else %}
        {% assign anchor = Model.ContentItem.Content.BlogPost.Image.Anchors.first %}
        <header class="masthead" style="background-image: url('{{ imagePath | asset_url | resize_url: profile:"banner", anchor: anchor }}')">
    {% endif %}
        <div class="container position-relative px-4 px-lg-5">
            <div class="row gx-4 gx-lg-5 justify-content-center">
                <div class="col-md-10 col-lg-8 col-xl-7">
                    <div class="post-heading">
                        <h1>{{ Model.ContentItem.DisplayText }}</h1>
                        <h2 class="subheading">{{ Model.ContentItem.Content.BlogPost.Subtitle.Text }}</h2>
                        <span class="meta">
                                    {% assign format = "%b %e, %Y" | t %}
                                    {% if Model.ContentItem.Content.BlogPost.PublicationDate.Value == "" %}
                                        {% assign date_value = Model.ContentItem.CreatedUtc | local %}
                                    {% else %}
                                        {% assign date_value = Model.ContentItem.Content.BlogPost.PublicationDate.Value %}
                                    {% endif %}
                                    {% assign dateTime = date_value | utc | date: format %}
                                    {{ "Posted by" | t }} <a href="#">{{ Model.ContentItem.Author }}</a> {{ "on {0}" | t: dateTime | raw }}
                        </span>
                    </div>
                </div>
            </div>
        </div>
    </header>
{% endzone %}

{{ Model.Content.ContentsMetadata | shape_render }}
{{ Model.Content.MarkdownBodyPart | shape_render }}
{{ Model.Content.BlogPost-Category | shape_render }}
{{ Model.Content.BlogPost-Tags | shape_render }}

{% assign recentBlogPosts = Queries.RecentBlogPosts | query %}
{% for item in recentBlogPosts %}
{{ item | display_text }}
{% endfor %}

This happens to be a slightly modified version of the default template from the blog recipe. Specifically, take note of the <span class="meta">...</span> that contains the "Posted by" text. Notice the three lines of liquid before the {{ "Posted by" | t}} that change the posted by date from the CreatedUtc to PublicationDate

{% assign format = "%b %e, %Y" | t %}
{% if Model.ContentItem.Content.BlogPost.PublicationDate.Value == "" %}
		{% assign date_value = Model.ContentItem.CreatedUtc | local %}
{% else %}
		{% assign date_value = Model.ContentItem.Content.BlogPost.PublicationDate.Value %}
{% endif %}
{% assign dateTime = date_value | utc | date: format %}

Click Save to save the overriden BlogPost template and see your new PublicationDate value appear.

Once this is done for the Content__BlogPost template, go back to the Edit Content Type - Blog Post page, and edit the template for Template for a Blog Post content item in summary views template. The code for this template is below.

<div class="post-preview">
    {% a display_for:Model.ContentItem %}
        <h2 class="post-title">
            {{ Model.ContentItem.DisplayText }}
        </h2>
        <h3 class="post-subtitle">
            {{ Model.ContentItem.Content.BlogPost.Subtitle.Text }}
        </h3>
    {% enda %}
    <p class="post-meta">
        {% assign format = "%b %e, %Y" | t %}
        {% if Model.ContentItem.Content.BlogPost.PublicationDate.Value == "" %}
            {% assign date_value = Model.ContentItem.CreatedUtc | local %}
        {% else %}
            {% assign date_value = Model.ContentItem.Content.BlogPost.PublicationDate.Value %}
        {% endif %}
        {% assign dateTime = date_value | utc | date: format %}
        {{ "Posted by" | t }} <a href="#">{{ Model.ContentItem.Author }}</a> {{ "on {0}" | t: dateTime | raw }}
  
        <span class="term-badge">
            {% assign categoryTerms = Model.ContentItem.Content.BlogPost.Category | taxonomy_terms %}
            {% for categoryTerm in categoryTerms %}
                {% a display_for:categoryTerm %}
                    <span class="badge bg-secondary">
                        <i class="{{ categoryTerm.Content.Category.Icon.Text }} fa-xs align-middle"></i>
                        <span class="align-middle">{{ categoryTerm.DisplayText }}</span>
                    </span>
                {% enda %}
            {% endfor %}

            {% assign tagTerms = Model.ContentItem.Content.BlogPost.Tags | taxonomy_terms %}
            {% for tagTerm in tagTerms %}
                {% a display_for:tagTerm %}
                    <span class="badge bg-secondary">
                        <i class="fas fa-tag fa-xs fa-rotate-90 align-middle" aria-hidden="true"></i>
                        <span class="align-middle">{{ tagTerm.DisplayText }}</span> 
                    </span>
                {% enda %}
            {% endfor %}
        </span>
    </p>
</div>
<hr class="my-4" />

Notice again, that this is a slightly modfied version of the default Blog Post Summary template from the Blog Recipe - the important lines are the following.

{% assign format = "%b %e, %Y" | t %}
{% if Model.ContentItem.Content.BlogPost.PublicationDate.Value == "" %}
		{% assign date_value = Model.ContentItem.CreatedUtc | local %}
{% else %}
		{% assign date_value = Model.ContentItem.Content.BlogPost.PublicationDate.Value %}
{% endif %}
{% assign dateTime = date_value | utc | date: format %}

Conclusion

OrchardCore makes it really easy to get up and running with a blog site. It's easy to migrate your posts over especially if they're already written in markdown. If you need to adjust how the post is stored and/or display, you can do that through the admin UI of OrchardCore.

If you found value in this post, consider following me on X @davidpuplava for more valuable information about Game Dev, OrchardCore, C#/.NET and other topics.