For SEO purpose, we are required to remove the default.aspx, index.aspx etc… from the website URLs.
Recently a very similar requirement came from one of our clients where they requested that any component links present within Tridion Pages should resolve to URLs NOT ending with default.aspx / index.aspx
There are two possible approaches to the problem here.
One, as suggested by Will in this excellent post. This seemed to be a winner until we realized possible issues & the overheads next to come.
For the custom extended linking to work, One has to de-register actual Tridion.ContentDelivery. dll and register the custom Control in web.config.
<add tagPrefix="Custom" namespace="Tridion.Custom.ExtendedLinks" assembly="Tridion.Custom.ExtendedLinks" /> <!--<add tagPrefix="tridion" namespace="Tridion.ContentDelivery.Web.UI" assembly="Tridion.ContentDelivery" />-->
Here now the problem arises. What about the other links: PageLink, BinaryLink etc… which are present inside the Tridion.ContentDelivery.Web.UI namespace ?
Obviously we will loose the dynamic linking functionality for such links if we extend only the ComponentLink.
Next thing, a possibility, was to extend all other Links and simply call the base’s class render method to keep such links working with their default functionality.
This required to override all nine other controls: BinaryLink, PageLink, ComponentPresentation, Condition, Conditions, DynamicComponentLink, IncrementKey, TargetGroup, TaxonomyControl )
This obviously seems to be bit of an overhead and a poor man’s solution to override/extend each Link class just to extend one!
Moreover, what if in future more Web Controls are introduced in Tridion Content Delivery?
The second solution was to dive into the template rendering process and modify the TCDL tags ,specific to Component Links, which are generated by Link Resolver TBB( present in Default Finish Action TBB).
A bit of a background:
A tridion Page links to other tridion Pages usually through the component links present in it. These Component Links after being processed by the Link Resolver TBB are converted to TCDL tags (on publish) as seen below:
<tcdl:Link type="Component" origin="tcm:123-250233-64" destination="tcm:123-654674" TemplateURI="tcm:0-0-0" AddAnchor="false" LinkText="Product" LinkAttributes=" class="productSection" title="Product" " textOnFail="true" addAnchor="false" variantId="">Product</tcdl:Link>
Such TCDL tags are then processed by the Content Deployer( on publishing) and there by converting them to server side Asp.Net controls such as:
<tridion:ComponentLink runat="server" PageURI="tcm:123-250233-64" ComponentURI="tcm:123-654674" TemplateURI="tcm:0-0-0" AddAnchor="false" LinkText="Product" LinkAttributes=" class="productSection" title="Product" " TextOnFail="true" />
Check this blog post for a brief explanation on TCDL tags processing.
Coming back to our second solution, this approach had few advantages
- Only the Component Link TCDL tags generated after processing by the Default Finish Action TBB will be converted to Custom server tags. All other links will be untouched and will continue with their default behavior.
- The Custom Tags will remain untouched by the Content Deployer when processing the incoming items (on Publishing).
- The actual Tridion.ContentDelivery.dll does not need to be commented/de-registered from Web.config, thus preserving the existing functionality for all other Tridion Dynamic links without any overheads!
Stage I: Processing at Content Manager
So, our goal was to convert the below Component Link TCDL tag
<tcdl:Link type="Component" origin="tcm:123-250233-64" destination="tcm:123-654674" templateURI="tcm:0-0-0" linkAttributes=" class="productSection" title="Product" " textOnFail="true" addAnchor="false" variantId="">Product</tcdl:Link>
to this Custom Server Tag:
<custom:ComponentLink runat="server" pageURI="tcm:123-250233-64" componentURI="tcm:123-654674" templateURI="tcm:0-0-0" addAnchor="false" linkText="Product" linkAttributes=" class="productSection" title="Product" " textOnFail="true"> </custom:ComponentLink>
And, to make sure this conversion happens before Content Deployer touches the item, a C# TBB/.Net Assembly needs to be in place after the Default Finish Actions TBB in the CTs.
A .Net Assembly as seen above, ConvertTCDLComponentLinkTagsToCustomTags, was created to process the Output item and perform a regular expression match and replace from TCDL Tags to Custom Server tags.
You may check the complete working/tested code on Git Hub. Explanation follows below.
Here is what the regular expression to match a TCDL Component Link looks like:
Each attribute is captured in a group with the same name as the attribute. As an example, to match & capture the attribute origin & it’s value, the regex part we have is:
This will match and place the captured value of origin attribute in the group named origin as seen below:
Same way, all other attributes are captured (and kind of stored) in a group with the same name as that of the attribute itself.
Once done with the Matching & Capturing of the attributes into Groups, a Class object representing the TCDL Component Link tag is generated.
Model Generated in Code:
Using the above model, another Class object representing our Custom Tag is generated:
Custom Tag’s Class object generated in code:
The final stage is to generate the Custom server tag for each TCDL tag matched which is done as:
The TCDL_CUSTOM_COMPONENT_LINK_TAG_SKELETON as seen in above code looks like below:
This will replace the original TCDL tags with our Custom Server tags. Since the Custom Server tag doesn’t matches any of the predefined tags which are processed by the Content Deployer, the final Page deployed on our servers will have all the Custom Server tags as it is.
STAGE II: Processing at Content Delivery Server
Done with the processing at Tridion’s CMS end, the Custom Server tag now needs to be processed at the server end which is done using a (usual) custom control created in Asp.Net.
Create a class library project and inherit the class from the class we wish to override: ComponentLink
Custom Control Class:
Overridden Render Method:
Register the custom control in Web.config and we are good to go!
<add tagPrefix="Custom" namespace="Tridion.Custom.ExtendedLinks" assembly="Tridion.Custom.ExtendedLinks" /> <add tagPrefix="tridion" namespace="Tridion.ContentDelivery.Web.UI" assembly="Tridion.ContentDelivery" />
Thus, any time the page is requested(in a browser), the Page’s inner links will have default.aspx or index.aspx removed!
You can open the .aspx Page in any text editor and view the custom tags there.
Hope you enjoyed this post interfering with the rendering/resolving processes of Tridion. Let me know, of the two approaches discussed, which one you think to be better and why!
Any further suggestions/feedback are always welcome.