Today I’ll go with the example suggested by Lars. Suppose we’re implementing a new money field type to store both the numeric amount and the currency (229 US Dollars). Both bits of information are stored in a single field using XML, which is a typical approach for Sitecore.
I’ll skip the whole implementing a new field type part (no need to repeat SDN); lets say that the Sitecore Client part is already implemented, and editors are able to use the Content Editor to change field value.
One problem remains – how to output money values on the website? The field contains XML, so we can’t just do sc:fld(‘money’, .). Different currencies have different signs which can go before or after the amount, which makes non-trivial rendering logic. The typical Sitecore 5 solution would be to implement a new XSL extension method and/or .NET web control.
In Sitecore 6, however, you can use the renderField pipeline to make existing rendering methods properly render custom field types.
Once again, this is a clean renderField pipeline:
<renderField>
<processor type="Sitecore.Pipelines.RenderField.GetFieldValue, Sitecore.Kernel"/>
<processor type="Sitecore.Pipelines.RenderField.ExpandLinks, Sitecore.Kernel"/>
<processor type="Sitecore.Pipelines.RenderField.GetImageFieldValue, Sitecore.Kernel"/>
<processor type="Sitecore.Pipelines.RenderField.GetLinkFieldValue, Sitecore.Kernel"/>
<processor type="Sitecore.Pipelines.RenderField.GetInternalLinkFieldValue, Sitecore.Kernel"/>
<processor type="Sitecore.Pipelines.RenderField.GetMemoFieldValue, Sitecore.Kernel"/>
<processor type="Sitecore.Pipelines.RenderField.GetDateFieldValue, Sitecore.Kernel"/>
<processor type="Sitecore.Pipelines.RenderField.AddBeforeAndAfterValues, Sitecore.Kernel"/>
<processor type="Sitecore.Pipelines.RenderField.RenderWebEditing, Sitecore.Kernel"/>
</renderField>
Most processors are responsible for rendering specific field types, plus there are some additional processors supporting Sitecore architecture.
Following the naming convention, we’ll create a new GetMoneyFieldValue processor and place it after all Get* processors, but before the AddBeforeAndAfterValues:
<processor type="Sitecore.Pipelines.RenderField.GetDateFieldValue, Sitecore.Kernel"/>
<processor type="Money.GetMoneyFieldValue, Money" /> <processor type="Sitecore.Pipelines.RenderField.AddBeforeAndAfterValues, Sitecore.Kernel"/>
The processor responsibility is to render HTML. I’m assuming that money field contains the following XML: <money currency=”USD” amount=”229.99” />
public class GetMoneyFieldValue {
public void Process(RenderFieldArgs args) {
if (args.FieldTypeKey != "money") {
return;
}
var doc = new XmlDocument();
doc.LoadXml(args.FieldValue);
string currency = doc.DocumentElement.GetAttribute("currency");
string amount = doc.DocumentElement.GetAttribute("amount");
string result = string.Empty;
if (currency == "USD") {
result = "$" + amount;
}
else if (currency == "DKK") {
result = amount + " kr.";
}
args.Result.FirstPart = result;
}
}
First, and most importantly, the processor has to check the type of the field being rendered. It’s only supposed to render money fields and ignore everything else. Then we retrieve the field value – notice the FieldValue property. The value is parsed, and depending on the currency we nicely render the monetary amount of either American dollars or Danish kroner. The result is stored in args.Result.FirstPart - money field is not supposed to be able to wrap other values, so nevermind the LastPart.
Why Bother?
Implementing the above processor gives website developers the ability to use standard Sitecore field rendering methods to properly render money fields. Developers can do sc:field(‘money’, .) or use the FieldRenderer class and never have a second thought.