Did you ever try to store a XhtmlString in a variable and use it in your code? Maybe you noticed that some stuff, like links, isn’t very useful because they are internal.
I noticed this when i upgraded a site from CMS6, and on that site i had a working code that rendered dynamic content so the code i passed to my variable actually was useful, but it broke when i upgraded the site. What i did find than, was that XhtmlStrings are made up of Fragments. And that’s really useful!
One thing you can do with these fragments is resolving internal links, and this is because links are stored as a UrlFragment. A typical XhtmlString could look like:
As you can see, we have regular content, UrlFragments and a ContentFragment. So now, we can write some code to do stuff with different fragements:
1 2 3 4 5 6 7 8 9 10 11 |
StringBuilder sBuilder = new StringBuilder(); foreach (IStringFragment sFragment in Xhtml.Fragments) { if (sFragment is ContentFragment) { } if (sFragment is UrlFragment) { } sBuilder.Append(sFragment.GetViewFormat()); } |
Maybe you would like to do something with a block?
1 2 3 4 5 |
if (sFragment is ContentFragment) { ContentFragment cFragment = sFragment as ContentFragment; var Content = Repository.Get<ContentData>(cFragment.ContentLink); } |
Or, if you would like to resolve links in your XhtmlString:
1 2 3 4 5 6 7 8 |
if(sFragment is UrlFragment) { UrlFragment uFragment = sFragment as UrlFragment; UrlBuilder uBuilder = new UrlBuilder(uFragment.InternalFormat); Global.UrlRewriteProvider.ConvertToExternal(uBuilder, null, Encoding.UTF8); sBuilder.Append(uBuilder.Uri); continue; } |
The complete code i use to resolve links before passing the content to a javascript:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public static string ParseXhtmlString(XhtmlString Xhtml) { StringBuilder sBuilder = new StringBuilder(); if (!(Xhtml == null || Xhtml.IsEmpty)) { foreach (IStringFragment sFragment in Xhtml.Fragments) { UrlFragment uFragment = sFragment as UrlFragment; if(uFragment != null) { try { UrlBuilder uBuilder = new UrlBuilder(uFragment.InternalFormat); Global.UrlRewriteProvider.ConvertToExternal(uBuilder, null, Encoding.UTF8); sBuilder.Append(uBuilder.Uri); continue; } catch (Exception) { } } sBuilder.Append(sFragment.GetViewFormat()); } } return sBuilder.ToString(); } |
Follow jonlin76
Thanks for sharing!
You could improve your type checking by just using ‘as’ and then null check:
var uFragment = sFragment as UrlFragment;
if (uFragment != null)
{
}
Now you’re only casting the object once, and not three times as in your original code. Way cleaner if you ask me 🙂
I would also recommend using the UrlResolver instead of the UrlRewriteProvider.
You are absolutely right about the casts. I better update the code before some one use it in a “copy/paste-solution” 🙂
You might also want to look into ToHtmlString http://world.episerver.com/documentation/Class-library/?documentId=cms/8/C94D982A
Thank you, it helped me a lot. Just one thing: you forgot to filter fragments: xhtml.Fragments.GetFilteredFragments(_principalAccessor.Principal); (where _principalAccessor is an injected IPrincipalAccessor)
also I’m trying to check if url fragment is internal link by:
if (urlFragment != null && urlFragment.ReferencedPermanentLinkIds.Count > 0)
Good point!