3

I have a C# TBB which takes a component, and should be pushing a link into the package stack.

  1. If the component is a publication, and it references a multimedia component, the link should be a link to that multimedia component.
  2. If the component is a publication, and it links to an external URL, the link should be that external URL.
  3. Otherwise, the link is just a broker link to that component ID.

I tried instantiating a Tridion.ContentDelivery.Web.Linking.ComponentLink object, but I get "could not load file or assembly 'Tridion.ContentDelivery, Version=6.1.0.348, Culture=neutral, PublicKeyToken=ddfc895746e5ee6b' or one of its dependencies", so I'm assuming I don't have access to that DLL from templating.

What does the below code need to do to return a valid URL?

private string getcomponentlink(Component c)
{
    string link = null;
    if (c.Schema.Id.ItemId == PUBLICATION_SCHEMA_ITEM_ID)
    {
        string doclink = getlink(c, "DocumentLink");
        string externallink = getlink(c, "ExternalDocumentLink");
        if (!String.IsNullOrWhiteSpace(doclink))
        {
            // TODO: need to convert from multimedia component TCM ID to proper link
            link = doclink;
        }
        else if (!String.IsNullOrWhiteSpace(externallink))
        {
            link = externallink;
        }
    }
    else
    {
        // TODO: need to convert from component TCM ID to proper link
        link = c.Id;
    }
    return link;
}

private string getlink(Component c, string field)
{
    var node = c.Content[field];
    var attrs = node != null ? node.Attributes : null;
    var linkattr = attrs != null ? attrs["xlink:href"] : null;
    string link = linkattr != null ? linkattr.Value : null;
    return link;
}

Solution

Here's the now working code.

    if (c.Schema.Id.ItemId == PUBLICATION_SCHEMA_ITEM_ID)
    {
        string docid = getlink(c, "DocumentLink");
        string externallink = getlink(c, "ExternalDocumentLink");
        if (!String.IsNullOrWhiteSpace(docid))
        {
            link = String.Format("href=\"{0}\"", docid);
        }
        else if (!String.IsNullOrWhiteSpace(externallink))
        {
            link = String.Format("href=\"{0}\"", externallink);
        }
    }
    if (String.IsNullOrWhiteSpace(link)) {
        link = String.Format("broker:href=\"{0}\"", c.Id);
    }

3 Answers 3

9

Dynamic Component Linking is a Content Delivery feature, not a Content Manager feature. You cannot create a component link when publishing, only when serving the page on the Content Delivery side.

Please explain what you mean with

component is a publication

Components are components, publications are publications. Or is publication a content type/schema in your context?

All you can do is generate the code pointing to the correct ID and let Tridion do the rest for you:

  • Have some logic determine which component you need to link to
  • Create the correct <a tridion:href="@@WhateverComponent.ID@@">text</a> that you need to output - though I use dreamweaver notation you can also create this in c#, as long as it is included in your Output Package item.
  • Use the default "Link Resolver" TBB at the end of your template

Tridion will do the rest from here.

2
  • Yes, in this context, "publication" is the schema - a schema for a piece of content that is being published. Thanks for the answer. :)
    – George
    Commented Mar 21, 2013 at 22:52
  • Thanks again for the answer - the code works now. In the "link to a broker item" case, there's some code that searches the rendered presentation on the CD side and converts "broker:href=1234" into a link to a page that renders the broker component. If I drop "href=1234" into the DWT the link to the binary is automatically sorted out.
    – George
    Commented Mar 22, 2013 at 6:27
3

I understand your requirement (by ignoring all the irrelevant things specified like component is publication etc), but at max you can do following:

1) For External URLs being provided in the component, you can directly push them on the stack by extracting in C# TBB through TOM.NET

2) For Multimedia Component, specify your File Server root path in the Publication Properties in Image URL and Image Path text boxes, and use this in C# TBB generate an absolute path

3) For Internal Component Link, you can not resolve it at Content Manager level as suggested by Nuno above and for this use the suggestion as mentioned by Nuno.

1

As Nuno details, link resolution is the responsibility of the content delivery service. It is possible to resolve links at publish, in a sense; however, you will lose a lot of sophisticated functionality relating to things like priorities and dynamic resolution accounting for publish states.

I can envisage scenarios in which it's useful to be able to resolve links at publish time, however, such as when generating control tags for a web.config file.

It is fairly simple, using TOM.Net, to produce a list of pages on which a component is used:

Component comp = engine.GetObject(someId) as Component;
List<Page> pages = GetPagesByComponent(component);

private List<Page> GetPagesByComponent(Component component)
{
    var pages = new List<Page>();
    var filter = new Filter();
    foreach (var item in component.GetUsingItems(filter))
    {
        pages.Add((Page)item);
    }
    return pages;
}

You can extend this to find the element of pages that you need. For example, in my case, I have an optional parameter for file extension, which I use to specify that I want to find the first '.ascx' page using this component, which I subsequently use as the src attribute in a user control registration. You can then access the (relative) published URL of the page with Page.PublishLocationUrl.

Content Delivery is the way to go wherever possible, however.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.