Thursday, September 22, 2011

Umbraco Razor Feature Walkthrough–Part 8

Welcome back!

Part 8 of the feature walkthrough continues with features available in umbraco 4.7.1
Today, I'm covering the new umbraco razor @Library added to the core.

This is now where all of the helper methods like GetNodeById will live, though they're aliased from @Model still, and any new functionality that may be added in the future.

By the way, in case you missed it, the uComponents team has already made a great start on the Razor Data Type Models! Go Team, #h5yr
Read all about this new feature in the last blog post here: /blog/umbraco-razor-feature-walkthrough-part-7/

@Library introduction

After writing a few methods such as NodeById and MediaById, I realised that these have nothing to do with the current @Model / DynamicNode / CurrentNode and they would be much better added to a seperate class.
After a discussion with a few of the more vocal razor users, we settled on creating a library class that can be accessed with @Library.
This class is of type RazorLibraryCore in the namespace umbraco.MacroEngines.Library.

There are a few methods available on it. This post and the next post will cover those features.

@Library Mix-Ins/Extensions - Add your own

@Library should allow you to create an extension method of your own and then call it from Razor.
Just create a simple extension method:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using umbraco.MacroEngines.Library; namespace RazorLibraryMixInTest { public static class MyRazorLibraryExtensions { public static string Foo(this RazorLibraryCore library) { return "Bar"; } } } 

Then, simply call it from your Razor script:

@using RazorLibraryMixInTest @Library.Foo() 


Coalesce, Concatenate and Join

These new methods on @Library allow you to manipulate multiple string parameters to combine them in various ways.
Coalesce will take the first non-null, non-DynamicNull property value and return the value of it.
Concatenate will just concatenate [really?] the parameters you pass in together as if you had gone @Model.property + @Model.property2
and Finally, Join will do the same as Concatenate, except takes a seperator parameter as the first parameter.

All of these methods are DynamicNull safe, so they'll ignore properties that don't exist on your document types.
Here's an example, they take params object[] so you should be able stack up as many properties as you need.

@Library.Coalesce(@Model.property1, @Model.property2, @Model.Name) 

Concatenate works the same way. Join has a slightly different syntax:

@Library.Join(",", @Model.property1, @Model.property2, @Model.Name) 


NodeById, NodesById

@Library.NodeById is the functionality from the 4.7.0 release where you can go @Model.NodeById(1546)
While building that implementation, I made the decision to add a method that took a list of ids and returned a DynamicNodeList.
This overload was inconsistent, as the name suggested that it returned a single node, when in fact it returned a list.
I've renamed this overload as NodesById.

Other than this change, the implementation is the same.

@Library.If

Library.If is more syntactic sugar for Razor than anything. It wraps a simple ternary:

<strong>@{ @Model.booleanProperty ? "valueIfTrue" : "valueIfFalse" }</strong> //is equivilent to: <strong>@Library.If(@Model.booleanProperty, "valueIfTrue", "valueIfFalse")</strong> 

Yes it's actually longer, but often when using embedded ternaries, e.g. inside an attribute value, you had to add extra brackets to get razor to parse the code properly.

@Library.ToDynamicXml

@Library.ToDynamicXml provides some methods to convert various types to DynamicXml. The overloads are as follows:

public DynamicXml ToDynamicXml(string xml) public DynamicXml ToDynamicXml(XElement xElement) public DynamicXml ToDynamicXml(XPathNodeIterator xpni) 

These methods are pretty much self explainatory, but the XPathNodeIterator method will allow you to convert your old XSLT Extensions to be easily accessible within Razor.
This is intended as a stepping stone only, if you're writing a new interface, you should return it as a List<StronglyTypedObject>

@Library.Truncate

This method is used to take a string (or a block of HTML) and truncate it to a specific length.
It will optionally add an elipsis on the end for you (… ) and it is HTML Tag aware.

There are a number of overloads, but the most basic use case is this:

@Library.Truncate(Model.rteContent,100) 

This will return the content of rteContent, but only the first 100 characters. Characters that are tags (e.g. <strong>) will not be counted towards the 100, and a … will be added on the end.
If the truncation occurs in the middle of a tag, (e.g. there'd be no </strong>) the tag will still be closed.

Disclaimer
: I haven't confirmed that the truncation will always close tags properly, I've fixed a number of issues that I've seen while testing with my own production sites but there may be cases where this method truncates wrongly, or breaks a tag. I suggest carefully testing to make sure it works for your use case.

Here are the other overloads:

public IHtmlString Truncate(IHtmlString html, int length) public IHtmlString Truncate(IHtmlString html, int length, bool addElipsis) public IHtmlString Truncate(IHtmlString html, int length, bool addElipsis, bool treatTagsAsContent) public IHtmlString Truncate(DynamicNull html, int length) public IHtmlString Truncate(DynamicNull html, int length, bool addElipsis) public IHtmlString Truncate(DynamicNull html, int length, bool addElipsis, bool treatTagsAsContent) public IHtmlString Truncate(string html, int length) public IHtmlString Truncate(string html, int length, bool addElipsis) public IHtmlString Truncate(string html, int length, bool addElipsis, bool treatTagsAsContent) 

Rather than explaining each of the overloads, which would be boring for all of us, there are 3 input types, and for each of those, 3 overloads.
addElipsis controls whether the … will be added and "treatTagsAsContent" effectively disables the HTML tag parsing portion of this method.

@Library.StripHTML

As the name suggests, this method will strip the HTML tags out of a block of HTML and return just the text. For example:

This is some text <strong> and this is some bold text</strong> in a sentence
Will become:
This is some text and this is some bold text in a sentence

This method will not deal with <script> or <style> tags properly, as they can have nested < and >.

Here are the overloads:

public HtmlString StripHtml(IHtmlString html) public HtmlString StripHtml(DynamicNull html) public HtmlString StripHtml(string html) public HtmlString StripHtml(IHtmlString html, List<string> tags) public HtmlString StripHtml(DynamicNull html, List<string> tags) public HtmlString StripHtml(string html, List<string> tags) public HtmlString StripHtml(IHtmlString html, params string[] tags) public HtmlString StripHtml(DynamicNull html, params string[] tags) public HtmlString StripHtml(string html, params string[] tags)

These methods are fairly self explainatory, but the simple use case is this:

@Library.StripHTML(Model.rteContent) 

If you only wanted to strip specific tags, such as the dreaded <pre>, you could do this:

@Library.StripHTML(Model.rteContent, "pre") 

Conclusion:

I've got one more blog post planned to introduce the last of the features that are in umbraco 4.7.1

I'm Gareth Evans, Follow me at @agrath on twitter, and here's a few links:
The new Razor forum on our.umbraco: http://our.umbraco.org/forum/developers/razor
Codeplex for any feature requests or bugs: http://umbraco.codeplex.com/

Read more from the Umbraco Razor walkthrough series

Umbraco Razor Feature Walkthrough - Part 1
Umbraco Razor Feature Walkthrough - Part 2
Umbraco Razor Feature Walkthrough - Part 3
Umbraco Razor Feature Walkthrough - Part 4
Umbraco Razor Feature Walkthrough - Part 5
Umbraco Razor Feature Walkthrough - Part 6
Umbraco Razor Feature Walkthrough - Part 7
Umbraco Razor Feature Walkthrough - Part 8

Want to be updated on everything Umbraco?

Sign up for the Umbraco newsletter and get the latest news and special offers send directly to your inbox

Are you sure, that's your real e-mail?