Links in Optimizely Cms: A guide
In Optimizely CMS there are several ways to link to internal or external content using different property types, and there are several ways to render these properties. This can be confusing, so here is an overview to hopefully make it easier to choose the best option
We will also take a look at the "on page edit" functionality in this matter, and make sure the links are properly localized..
This article is based on Optimizely Cms 12 with razor views, and the Alloy solution is used for demonstration.
Choose the correct property type
First, we will map out the different property types available.
Link to pages
There are two options when creating a property for linking to other pages:
- ContentReference: A good option if there is no need for linking to external content. You can also limit which pagetype should be allowed, using annotation.
public virtual ContentReference Link1 { get; set; }
- Url: If you want a simple property for linking both internally and externally.
public virtual Url Link2 { get; set; }
Images
- Url with UIHint.Image: If you want a property for choosing an image, you can use the Url property with a UIHint.
The UIHint can also be used for the ContentReference type.[UIHint(UIHint.Image)]
public virtual Url Link3 { get; set; }
General links
- LinkItem: If you want a property for adding a link to either internal or external content, the best option is LinkItem. This will give you some extra attributes, which is described later on.
public virtual LinkItem Link5 { get; set; }
- LinkItemCollection: If you want the possibility to add multiple links, like a link list, you can use LinkItemCollection:
public virtual LinkItemCollection Link4 { get; set; }
Choose how to render the property
Now, when you have chosen the preferred property type, the next step is to choose the correct way to render the property.
Unformatted
The Url property can be rendered directly, with no formatting, but this will not give you a friendly url.
- Url:
<a href="@Model.CurrentPage.Link2">Link</a>
Result:<a href="/link/fdac9c5f86b64223b4a6397fe72483f9.aspx">Link</a>
- Url with UIHint for image:
<img src="@Model.CurrentPage.Link3" width="50"/>
Result:<img src="/link/6f97d70164be4681975690d8f8c05379.aspx" width="50">
Friendly urls and localization
To make sure you get a url which takes into account localization and gives you a user friendly url, you should use the UrlResolver in backend and the UrlHelper in the views. Here is how to do this for the different property types:
Razor views:
- ContentReference:
<a href="@Url.ContentUrl(Model.CurrentPage.Link1)">Link</a>
Result:
<a href="/no/alloy-plan/">Link</a>
- Url:
<a href="@Url.ContentUrl(Model.CurrentPage.Link2.Uri.ToString())">Link</a>
Result:
<a href="/en/alloy-plan/">Link</a>
- Url with UIHint for image:
<img src="@Url.ContentUrl(Model.CurrentPage.Link3.Uri.ToString())" width="50" />
Result:
<img src="/globalassets/pexels-binoculars.jpg" width="50">
- LinkItem:
<a href="@Url.ContentUrl(Model.CurrentPage.Link5.Href)">Link</a>
Result:
<a href="/en/alloy-plan/">Link</a>
- LinkItemColleciton:
You will have to loop through the items in the LinkitemCollection to render each item the same way as the LinkItem above
<ul>
@foreach (var link in Model.CurrentPage.Link4){
<li><a href="@Url.ContentUrl(link.Href)">Link</a></li>
}
</ul>
Result:
<ul>
<li><a href="/en/alloy-plan/">Link</a></li>
<li><a href="/en/alloy-track/">Link</a></li>
</ul>
Backend:
- For backend it will be similar, just use an instance of the urlResolver instead.
UrlResolver _urlResolver;
(…)
var url = _urlResolver.GetUrl(startPage);
LinkItem
Let's take a closer look at the LinkItem property. Previously, it was only available as part of the LinkItemCollection and could not be used independently. It is now available as a standalone property type, which is very convenient. The Url property gives you a simple way to add a url, whereas the LinkItem lets you store information such as text, target and link attributes. It also provides these methods:
- GetMappedHref():
/link/fdac9c5f86b64223b4a6397fe72483f9.aspx
- ToMappedLink():
<a title="Link to Alloy Plan" href="/link/fdac9c5f86b64223b4a6397fe72483f9.aspx">Read more about Alloy Plan</a>
- ToPermanentLink():
<a title="Link to Alloy Plan" href="~/link/fdac9c5f86b64223b4a6397fe72483f9.aspx">Read more about Alloy Plan</a>
None of these gives you a friendly or localized url though.
On page edit
The on page edit is a useful mode for the editor, so you should put in some effort to make it function properly.
There are three different ways to add this functionality:
- The good old "@Html.PropertyFor"
- The newer version "epi-property"
- And the helpful "@Html.EditAttributes" which can come into rescue where the above mentioned is not sufficient
All of them gives the same on page edit functionality. Example of the three options used with the Url property:
-
@Html.PropertyFor(x => Model.CurrentPage.Link2)
-
<a href="@Model.CurrentPage.Link2" epi-property="@Model.CurrentPage.Link2">Link</a>
-
<a href="@Model.CurrentPage.Link2" @Html.EditAttributes(x => Model.CurrentPage.Link2)>Link</a>
Now, there are some differences to the rendered markup. Number 2 and 3 will give you a simple link:
<a href="/link/fdac9c5f86b64223b4a6397fe72483f9.aspx">Link</a>
But number 1 will gives you significantly more out of the box. It provides a friendly url, automatically uses the page name as the link text, and ensures the link is properly localized for the correct culture.
<a href="/en/alloy-plan/">Alloy Plan</a>
Lets check out another example - the LinkItemCollection. As you remember from earlier, you had to manually loop through the items and render them one by one. If you want a simpler solution, you can use the Html.PropertyFor.
@Html.PropertyFor(x => Model.CurrentPage.Link4)
This will create the following markup:
<ul>
<li>
<a href="/en/alloy-plan/" title="Link to Alloy Plan">Read more about Alloy Plan</a>
</li>
<li>
<a href="/en/alloy-track/" title="Link to Alloy Track">Read more about Alloy Track</a>
</li>
</ul>
So the Html.PropertyFor gives you a full markup with on page edit and properly localized urls. Pretty nice - but there is one drawback. You don't have any control of the markup, regarding e.g. adding css classes.
Absolute Url
Often, you will need an absolute url, not just a relative one. To achieve this, you can combine the relative url you have obtained using one of the methods mentioned earlier, with the site url:
var siteUrl = SiteDefinition.Current.SiteUrl.AbsoluteUri.TrimEnd('/');
var absoluteUrl = string.Concat(siteUrl, url);
This gives you an absolute url: https://localhost:5080/en/alloy-plan/
Summary
We have looked at different property types for creating link properties in Optimizely Cms 12:
- The ContentReference is for linking to an internal page
- The Url and the LinkItem can be used for linking internally or externally, where the latter lets you apply attributes like text, title and target
- The Url with a UIHint annotation will let you link to media
- The LinkItemCollection is convenient when you need multiple links
We looked at different ways to render each property type:
- Unformatted: works for the Url property
- Friendly, localized url: obtained using the UrlHelper for frontend and UrlResolver for backend
- On page edit: different ways of rendering while maintaining the on page edit functionality
Finally, we looked at different ways to maintain the on page edit functionality for these property types.
- @Html.PropertyFor
- epi-property
- @Html.EditAttributes
I hope this was helpful! Please let me know if you have any feedback.
Comments