ItemDisplayLink & GetItemMetadata

Topics: Customizing Orchard
Mar 8, 2012 at 7:56 PM

I know I've done this before but something isn't working as expected now ... probably I'm doing something wrong.

I have a content type called "Movie" which has a MoviePart. In a view on my site I have a collection of Movie content items, and I'm looping over them to generate a <ul> list of links like this:

@foreach (dynamic movie in Model.Movies) {
    <li>@Html.ItemDisplayLink((IContent)movie)</li>
}

That works great and I get links where the Title property from the TitlePart is the text of the link. Now I want to customize the text of the link (without modifying the view - I want to have this happen on other places in the site too). So in my MovieHandler I override GetItemMetadata like so

protected override void GetItemMetadata(GetContentItemMetadataContext context) {
    var movie = context.ContentItem.As<MoviePart>();
    if (movie != null) {
        context.Metadata.DisplayText = string.Format("{0} ({1})", context.ContentItem.As<TitlePart>().Title, movie.YearReleased);
    }
}
I can put a breakpoint in that method and see that it's properly modifying the DisplayText property for the appropriate content items. However the ItemDisplayLink helper doesn't see it - I still get the default text of just the title. What am I missing? Like I said I know I've done this before and it works.

Coordinator
Mar 8, 2012 at 9:05 PM

Maybe a bug ... would you try it on 1.3 and see what has changed regarding this ? If you can't I will.

Mar 8, 2012 at 9:21 PM

I probably won't be able to today, but I can do it tomorrow if you don't get to it.

Mar 9, 2012 at 2:48 AM

Well, now I'm really confused because I can't get it to work on 1.3 either. I know I've done this before though - I did it for FeaturedItemSlider. I must be doing something wrong but I can't tell what it is.

Coordinator
Mar 9, 2012 at 2:56 AM

Actually you can call both ItemDisplayText and DisplayUrl 

Mar 9, 2012 at 1:16 PM

But DisplayUrl only gives you back the URL. I want ItemDisplayText because I want it to generate the link consistently and only specify how the text is formatted in one place (which should be the GetItemMetadata override in the Handler).

The problem appears to be that my Handler is working but it's getting overridden later by the TitlePartHandler in Orchard.Framework (and I assume the same thing is happening with a RoutePartHandler in 1.3):

protected override void GetItemMetadata(GetContentItemMetadataContext context) {
    var part = context.ContentItem.As<ITitleAspect>();

    if (part != null) {
        context.Metadata.DisplayText = part.Title;
    }
}
That's why it works for my FeaturedItemSlider module. Those content types don't have a Route/TitlePart. So the problem is the order that the handlers are being run. It would be nice if somehow I could indicate that the handlers in my module should be run last for the types that it declares. I realize this is probably impossible since content types aren't strongly typed, and you'd end up with modules disputing who gets to be last. That doesn't mean I don't want it though. :-)

Coordinator
Mar 9, 2012 at 5:03 PM

You can. Just take a dependency on Title. Done.

To come back to my suggestion, I am sure that given a Url (DisplayUrl) and a text (DisplayText) you can create a nice link ! Think simple ... got it ?

Mar 9, 2012 at 5:58 PM

Doesn't work. There are two TitlePartHandlers in the list. Even with the dependency declared in Module.txt, Orchard.Core.Title.Handlers.TitlePartHandler is 2nd in the list, but Orchard.ContentManagement.TitlePartHandler is always last. And it's that last one that sets the DisplayText property, overriding what my handler is doing.

And yes, I know that I can create a nice link manually using the DisplayUrl. I guess I'm not explaining very well why I wanted to do this. :-)

I want to stay DRY. There may be several views where I'm rending a link to content items of this type. Whenever that happens I want the text to be formatted the same way. There may even be other modules elsewhere in Orchard that call ItemDisplayLink to render links to my content items (that's what it's there for). I want those to be formatted the same way too. Setting DisplayText on the Metadata is the way to do that. Except it doesn't work because Title always overrides it.  :-)

It's not a big deal, it just seemed like a good way to demonstrate another thing you can do with a Handler. I'll leave it out since it doesn't work as expected. I've got plenty of other material to cover. :-)

Coordinator
Mar 9, 2012 at 6:29 PM

This might be a bug ... file it !

Mar 9, 2012 at 7:15 PM

Okay, here it is: http://orchard.codeplex.com/workitem/18548