How to customize the recent blog posts only on the home page!

Topics: Writing themes
Apr 22, 2013 at 4:00 PM
Hi Guys,

Is there a way to customize the recent blog posts but only for the home page?
In my theme I have a view that has the following name: Widget-RecentBlogPosts-url-homepage.cshtml and I have enabled the URL alternates but this view is not rendered.

Most important I am trying to find out where is all the markup for the recent blog posts coming from. I looked at the Parts.Blogs.RecentBlogPosts.cshtml in the Blogs module but all there is to it is just: @Display(Model.ContentItems) :-). I looked at all the blog views but again could not find where all the markup is coming from. I am suspecting that it might be coming from some default rendering of the blog parts but how is this possible!?

Really would like to understand more about this rather than blindly coding a theme in Orchard!

Thanks
Developer
Apr 22, 2013 at 4:24 PM
You'll be able to find out if you do the following:

In the Parts.Blogs.RecentBlogPost.cshtml file, set a breakpoint and have the debugger break there.
Inspect the shape type of Model.ContentItems (hover over Model, expand ContentItems and inspect its Metadata.Type property).
You will see what its type is, and based on that, find out what the type is of each item in the list.

So you have a choice: override the template for the shape type of the individual items.
Or, completely take over rendering by not rendering Model.ContentItems (which I believe is a List shape), but instead render each item in a foreach loop, giving you simple control over what HTML to use.
Use the debugger to inspect the object models and see what objects are available, what type they are and what properties they contain.
Apr 23, 2013 at 2:20 PM
Hi,

Thanks for your suggestions! I overrided the Parts.Blogs.RecentBlogPost.cshtml file and here is my code:
@using Orchard.ContentManagement
@{

    IEnumerable<dynamic> blogPosts = Model.ContentItems.ContentItems;
    
}

@if (blogPosts == null || !blogPosts.Any())
{
    
    <p>@T("No blog posts.")</p>
    
}
else
{

    foreach (dynamic blogPost in blogPosts)
    {
        string blogPostTitle = blogPost.Title;
        string blogText = blogPost.Text;
        string blogPublishedUtc = blogPost.PublishedUtc.ToString("MM dd, yyyy");
ContentItem contentItem = blogPost.ContentItem;
        
        var metadata = contentItem.ContentManager.GetItemMetadata(contentItem);
        string blogPostUrl = metadata.DisplayRouteValues["action"].ToString();
        
    <ul class="post-carousel clearfix" data-auto="0" data-scroll_count="">

            <li>
                <div class="entry-body">
                    <a href="@blogPostUrl" title="@blogPostUrl" rel="bookmark">
                        <h1 class="title">@blogPostTitle</h1>
                    </a>

                    @blogText

                </div>

                <div class="entry-meta">

                    <a href="@blogPostUrl" title="@blogPostUrl" rel="bookmark">
                        <span class="post-format ">Permalink</span>
                    </a>
                    <span class="date">
                         <a href="@blogPostUrl" title="@blogPostUrl" title="@blogPublishedUtc" rel="bookmark">
                            <time datetime="@blogPublishedUtc" pubdate>@blogPublishedUtc</time>
                        </a>
                    </span>
                </div>
            </li>
    </ul>

    }
}
It is tottally wrong. The blogPost objects are of type Content, I cannot get the Title, the Text or whatever data I need from a blog post.
I am digging with the debugger and it seems to me that there is no way to get the data that I need for a blog post. Really frustrating to be honest, for such a simple task!

I do not understand where the ContentItems property is coming from on the Model and even on the ContentItems itself? Why the Model.ContentItems enumerator does not return anything while the Model.ContentItems.ContentItems does? I cannot even understand of what type the Model is? The debugger shows Parts_Blogs_RecentBlogPosts, which I believe is the RecentBlogPostsPart class but this class has only two properties:
public class RecentBlogPostsPart : ContentPart<RecentBlogPostsPartRecord> {

        public int BlogId {
            get { return Record.BlogId; }
            set { Record.BlogId = value; }
        }

        [Required]
        public int Count {
            get { return Record.Count; }
            set { Record.Count = value; }
        }
    }
Digging in to the base ContentPart does not reveal anything either. Should I be getting the Record property and fetching the data from it. It seems wrong to do this in a view?

Please advise!

Thanks
Coordinator
Apr 24, 2013 at 3:20 AM
You can get to other parts using the As extension method: someContentPart.As<TitlePart>().Title.
Apr 24, 2013 at 11:22 AM
Ok, thanks Bertrand! I managed to do this but I had to cast the ContentItem to IContent before using the As method, otherwise it would not work:
var blogPostPart = ((IContent)blogPost.ContentItem).As<BlogPostPart>();
Here is my code:
@using Orchard.Autoroute.Models
@using Orchard.Blogs.Models
@using Orchard.ContentManagement
@{

    IEnumerable<dynamic> blogPosts = Model.ContentItems.ContentItems;
    
}

@if (blogPosts == null || !blogPosts.Any())
{
    
    <p>@T("No blog posts.")</p>
    
}
else
{

    foreach (dynamic blogPost in blogPosts)
    {
        var blogPostPart = ((IContent)blogPost.ContentItem).As<BlogPostPart>();
        string blogPostTitle = blogPostPart.Title;
        string blogText = blogPostPart.Text;
        string blogPublishedUtc = blogPostPart.PublishedUtc.Value.ToString("MM, dd yyyy");

        var autoRoutePart = ((IContent)blogPost.ContentItem).As<AutoroutePart>();

        string blogPostUrl = autoRoutePart.Path;
}
One final question if I may? I did ask a couple more in the previous post but I did not hope to get them answered anyway.

To achieve what I have done I had to reference the Orchard.Blogs and the Orchard.AutoRoute module in my theme project.
Is this wrong or it is a normal practice?

Thanks
Coordinator
Apr 25, 2013 at 3:05 AM
If you don't want to reference those, you can go through the dynamic behavior of ContentItem. For example:
dynamic item = contenItem;
var title = item.TitlePart.Title;