Categories
Bloggers
Blogs RSS feed

Dynamically resolving Sitefinity links when using HtmlField

by Stanislav Velikov

This is a solution to dynamically resolving links for sites running version of sitefiity lower than 5.4 sites. Sitefintiy 5.4 provides this out of the box.

When using HtmlField in user control or by adding custom fields of type LongText to Sitefinity modules and selecting pages, images, documents or videos using the built in selectors for those the link to the selected content or page Sitefinity will generate:

<a href="/page" SFREF="[F669D9A7-009D-4D83-DDAA-000000000002]BDC53495-7357-4B44-82D9-572C1A71374E">Page</a>
 the link indicates the selected page url is ~/page and the other attribute added to the link "SFREF" is used to resolve the proper link to the page selected if its moved to antother url.

For example if the page is moved under another page its url will be ~/parent/page

When selecting pages or media content in Sitefinity built in ContentBlock widget which used HtmlField the link is resolved automatically if the page or image has been moved to new location or their url was changed.

 If you use HtmlField or LongText field in user control or as custom field in module you will not get the automatic link resolution.

To fix this when rendering the html entered in the HtmlField use use Sitefinity LinkParser class

//get the html from HtmlField and convert it in formt usable for ResolveLinks method
var fixedHtml = LinkParser.UnresolveLinks(Name);
 
//resolve the links if there has been a change in the url
            NameLiteral.Text = LinkParser.ResolveLinks(fixedHtml, DynamicLinksParser.GetContentUrl, null, false);

 Attached is a user control utilizing html and implementiong the use of LinkParser.

 

When using LongText field as custom field to modules the selected media or pages links also will not resolve and to overcome this, create a custom htmlField (the long text field is htmlfield control), which inherits from the default one and override GetStringValue method to use LinkParser

public class HtmlFieldCustom : HtmlField
  
{
  
    protected override string ScriptDescriptorType
  
    {
        get
        {
            return typeof(HtmlField).FullName;
        }
  
    }
  
    public override string GetStringValue(object value)
    {
        var val = base.GetStringValue(value);
  
        var fixedHtml = LinkParser.UnresolveLinks(val);
  
        val = LinkParser.ResolveLinks(fixedHtml, DynamicLinksParser.GetContentUrl, null, false);
  
        return val;
    }
}
 If you have added the field to News module (for other modules the appraoch is the same) edit the module widget template and in the template register the namespace of the class created above and use the class to render the LongText field.

<%@ Control Language="C#" %>
  <%@ Register TagPrefix="sf" Namespace="SitefinityWebApp" Assembly="SitefinityWebApp" %>
<%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.PublicControls.BrowseAndEdit" Assembly="Telerik.Sitefinity" %>
  
<telerik:RadListView id="listsControl" runat="server"
                     ItemPlaceholderId="ListContainer"
                     EnableEmbeddedSkins="false"
                     EnableEmbeddedBaseStylesheet="false">
  
    <LayoutTemplate>
        <div class="sfexpandableListWrp">
            <div class="sflistExpandAllLnkWrp">
                <asp:LinkButton ID="listExpandAllLnk" runat="server" class="sflistExpandAllLnk" Text="<%$ Resources:Labels, ExpandAll %>" OnClientClick="return false;" />
                <asp:LinkButton ID="listCollapseAllLnk" runat="server" class="sflistCollapseAllLnk" style="display: none;" Text="<%$ Resources:Labels, CollapseAll %>" OnClientClick="return false;" />
            </div>
            <asp:PlaceHolder id="ListContainer" runat="server" />
  
        </div>
    </LayoutTemplate>
    <ItemTemplate>
  
            <h2 class="sflistTitle">
  
                <asp:Literal runat="server" Text='<%# Eval("Title") %>' />
  
            </h2>
  
            <telerik:RadListView ID="listItemsControl" runat="server"
  
                    ItemPlaceholderID="ItemsContainer"
   
                    EnableEmbeddedSkins="false"
  
                    EnableEmbeddedBaseStylesheet="false">
  
                <LayoutTemplate>
  
                    <ul class="sflistList">
  
                        <asp:PlaceHolder ID="ItemsContainer" runat="server" />
  
                    </ul>
  
                </LayoutTemplate>
  
                <ItemTemplate>
  
                    <li class="sflistListItem">
  
                        <h3 class="sflistItemTitle">
  
                            <asp:LinkButton runat="server" ID="listItemToggleLnk" class="sflistItemToggleLnk" Text='<%# Eval("Title") %>' OnClientClick="return false;" />
  
                        </h3>
  
                        <div runat="server" ID="listItemContent" class="sflistItemContent" style="display: none;">
  
                            <asp:Literal runat="server" Text='<%# Eval("Content") %>' />
                          <sf:HtmlFieldCustom runat="server" DisplayMode="Read" Value='<%# Eval("TestField")%>' />
                        </div>
 

4 comments

Leave a comment
  1. Nidhi Feb 15, 2013

    I was having this issue in custom widgets where I used the HTMLField and this fixed it. Thank you!

  2. Stephen Mar 03, 2013
    Thank you very much!!  (and for making this default in 5.4)
  3. Markus Jul 11, 2014
    Problem seams to still exist in 7.0 :-(
  4. Markus Jul 16, 2014

    It's a bug http://feedback.telerik.com/Project/153/Feedback/Details/133686-link-parser-does-not-work-in-dynamic-item-widget-in-list-mode

    Markus

    Leave a comment