Glass Mapper 5.0 BeginRenderLink Issue with Internal Links
Recently, I had an issue where internal links rendered using Glass Mapper 5 @Html.BeginRenderLink() were not rendering correctly. These internal links were created programmatically by a custom API. I noticed that an internal link created from Sitecore UI was getting rendered correctly, but the internal link created programmatically wasn’t rendering correctly.
YML of an internal field looks like this:
<link text="Link Text" anchor="" linktype="internal" class=""
title="Link Title" querystring="" id="{SOME-GUID}" />
YML of an external link looks like this:
<link linktype="external" url="https://www.reading.ac.uk" anchor="" target="" />
I used to following code to create an internal link field programmatically.
newItem.Editing.BeginEdit();
newItem["Title"] = model.Title;
newItem["Description"] = model.Description;
newItem["Link"] = $"<link text=\"{model.ItemName}\" anchor=\"\" " +
"linktype=\"internal\" " +
"class=\"\" title=\"\" querystring=\"\" id=\"{newItem.ID}\" />";
newItem.Editing.EndEdit();
In our system, the items get indexed and the index is queried to retrieve the items to display on a controller rendering. The indexing provider converted the Link field into Sitecore.Data.Fields.LinkField and then converted it into Glass.Mapper.Sc.Fields.Link. I had assumed that Glass Mapper uses URL field to render an external link and target id to render an internal link and wrote this code, which did not work
LinkField linkFieldUrl = new LinkField(newItem.Fields["Link"]);
Link lUrl = new Link()
{
Url = linkFieldUrl.Url,
Anchor = linkFieldUrl.Anchor,
Class = linkFieldUrl.Class,
Query = linkFieldUrl.QueryString,
Style = linkFieldUrl.QueryString,
Target = linkFieldUrl.Target,
TargetId = linkFieldUrl.TargetID.Guid,
Text = linkFieldUrl.Text,
Title = linkFieldUrl.Title
};
The linkFieldUrl.Url value is null for an internal link and Glass Mapper 5 simply uses the Url field to render the link. It ignores the LinkType and TargetId altogether, which makes absolutely no sense.
I had to change the mapping to this
LinkField linkFieldUrl = new LinkField(newItem.Fields["Link"]);
Link lUrl = new Link()
{
Url = linkFieldUrl.LinkType.ToLower() == "internal" ?
Sitecore.Links.LinkManager.GetItemUrl(newItem) : linkFieldUrl.Url,
Anchor = linkFieldUrl.Anchor,
Class = linkFieldUrl.Class,
Query = linkFieldUrl.QueryString,
Style = linkFieldUrl.QueryString,
Target = linkFieldUrl.Target,
TargetId = linkFieldUrl.TargetID.Guid,
Text = linkFieldUrl.Text,
Title = linkFieldUrl.Title,
Type = linkFieldUrl.LinkType.ToLower() == "internal" ?
LinkType.Internal : LinkType.External
};
If the link is INTERNAL, get the item URL using Sitecore.Links.LinkManager and use the direct URL from YML for external links.
I added the Type but it is largely ignored by the Glass Mapper.