Exam Area: Area 3 – Website Implementation & Delivery (25%)
Reference: https://docs.developers.optimizely.com/content-management-system/docs/links-and-references
// ContentReference is the fundamental type for referencing content
var link = new ContentReference(123); // By ID
var withVersion = new ContentReference(123, 456); // ID + Version
var withProvider = new ContentReference(123, 0, "myProvider"); // Custom provider
// Properties
link.ID // int: content ID
link.WorkID // int: version ID (0 = published)
link.ProviderName // string: content provider name
// Utilities
ContentReference.IsNullOrEmpty(link) // null check
link == ContentReference.EmptyReference // empty check
// Convert to URL (via IUrlResolver)
var url = urlResolver.GetUrl(link);
using EPiServer.Web.Routing;
public class LinkService
{
private readonly IUrlResolver _urlResolver;
public LinkService(IUrlResolver urlResolver)
{
_urlResolver = urlResolver;
}
// ContentReference → URL string
public string GetUrl(ContentReference link)
{
return _urlResolver.GetUrl(link);
}
// ContentReference → URL with language
public string GetUrlInLanguage(ContentReference link, string language)
{
var args = new VirtualPathArguments
{
ContextMode = ContextMode.Default
};
return _urlResolver.GetUrl(link, language, args);
}
// URL string → ContentReference
public ContentReference ResolveUrl(string url)
{
return _urlResolver.Route(new UrlBuilder(url))?.ContentLink;
}
}
@inject IUrlResolver UrlResolver
@* Use URL helper *@
<a href="@Url.ContentUrl(Model.CurrentPage.ContentLink)">Home</a>
@* Render ContentReference as link *@
<a href="@UrlResolver.GetUrl(Model.CurrentPage.RelatedPage)">Related</a>
@* Image URL *@
<img src="@Url.ContentUrl(Model.CurrentPage.HeroImage)" alt="Hero" />
// Block containing links
public class NavigationBlock : BlockData
{
[Display(Name = "Links")]
public virtual LinkItemCollection Links { get; set; }
}
// Render in View
@foreach (var link in Model.CurrentBlock.Links ?? new LinkItemCollection())
{
<a href="@link.Href" target="@link.Target">@link.Text</a>
}
// Permanent link – stable even when the URL changes
// Format: /link/{GUID}
// Get permanent link
public string GetPermanentLink(ContentReference link)
{
var page = _contentLoader.Get<PageData>(link);
return $"/link/{page.ContentGuid}";
}
// PermanentLinkMapper
public class PermanentLinkService
{
private readonly IPermanentLinkMapper _permanentLinkMapper;
public ContentReference ResolveGuid(Guid contentGuid)
{
var map = _permanentLinkMapper.Find(contentGuid);
return map?.ContentReference;
}
}
// ContentReference for internal links
public virtual ContentReference InternalLink { get; set; }
// Url type for external links
public virtual Url ExternalLink { get; set; }
// LinkItemCollection – mix of internal/external
public virtual LinkItemCollection MixedLinks { get; set; }
// Relative URL (default)
var relativeUrl = _urlResolver.GetUrl(link); // /my-page/
// Absolute URL (for email, sitemap, etc.)
var baseUrl = SiteDefinition.Current.SiteUrl;
var absoluteUrl = baseUrl + relativeUrl.TrimStart('/');
// Or use the ForceAbsolute argument
var externalUrl = _urlResolver.GetUrl(
link,
null,
new VirtualPathArguments { ForceAbsolute = true });
// Create a redirect page
var shortcutPage = _contentRepository.GetDefault<PageData>(parentLink);
shortcutPage.Name = "Old URL";
shortcutPage.LinkType = PageShortcutType.External;
shortcutPage.ExternalURL = "https://new-site.com/new-page";
_contentRepository.Save(shortcutPage, SaveAction.Publish);
// Shortcut to an internal page
shortcutPage.LinkType = PageShortcutType.Shortcut;
shortcutPage.ShortcutLink = new ContentReference(targetPageId);
IUrlResolver.GetUrl(link) return? (A relative URL string for the content)ContentReference vs Url property type – when should each be used? (ContentReference: internal CMS pages; Url: external URLs)PageShortcutType.External used for? (Redirecting a page to an external URL)ForceAbsolute = true or concatenate SiteUrl + relative path)