Earlier today while preparing a training session on how to add JavaScript from a Multi-Line Text field to a rendered Sitecore page, I encountered something I had seen in the past but forgot about: Sitecore FieldControls and the FieldRenderer Web Control will convert newlines into HTML breaks.
For example, suppose you have the following JavaScript in a Multi-Line Text field:
You could use a Text FieldControl to render it:
<%@ Control Language="c#" AutoEventWireup="true" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %> <sc:Text ID="scJavaScript" Field="JavaScript" runat="server" />
Unfortunately, your JavaScript will not work since it will contain HTML breaks:
Why does this happen? In the RenderField() method in Sitecore.Web.UI.WebControls.FieldRenderer — this lives in Sitecore.Kernel.dll, and is called by all FieldControls — passes a “linebreaks” parameter to the <renderField> pipeline:
The Process() method in Sitecore.Pipelines.RenderField.GetMemoFieldValue — this serves as one of the “out of the box” processors of the <renderField> pipeline — converts all carriage returns, line feeds, and newlines into HTML breaks:
What can we do to prevent this from happening? Well, you could spin up a new class with a Process() method to serve as a new <renderField> pipeline processor, and use that instead of Sitecore.Pipelines.RenderField.GetMemoFieldValue:
using System; using Sitecore.Diagnostics; using Sitecore.Pipelines.RenderField; namespace Sitecore.Sandbox.Pipelines.RenderField { public class GetRawMemoFieldValueWhenApplicable { public void Process(RenderFieldArgs args) { Assert.ArgumentNotNull(args, "args"); if(!AreEqualIgnoreCase(args.FieldTypeKey, "memo") && !AreEqualIgnoreCase(args.FieldTypeKey, "multi-line text")) { return; } bool omitHtmlBreaks; if (bool.TryParse(args.Parameters["omitHtmlBreaks"], out omitHtmlBreaks)) { return; } Assert.IsNotNull(DefaultGetMemoFieldValueProcessor, "DefaultGetMemoFieldValueProcessor must be set in your configuration!"); DefaultGetMemoFieldValueProcessor.Process(args); } private static bool AreEqualIgnoreCase(string stringOne, string stringTwo) { return string.Equals(stringOne, stringTwo, StringComparison.CurrentCultureIgnoreCase); } private GetMemoFieldValue DefaultGetMemoFieldValueProcessor { get; set; } } }
The Process() method in the class above looks for an “omitHtmlBreaks” parameter, and just exits out of the Process() method when it is set to true — it leaves the field value “as is”.
If the “omitHtmlBreaks”parameter is not found in the RenderFieldArgs instance, or it is set to false, the Process() method delegates to the Process() method of its DefaultGetMemoFieldValueProcessor property — this would be an instance of the “out of the box” Sitecore.Pipelines.RenderField.GetMemoFieldValue, and this is passed to the new <renderField> pipeline processor via the following configuration file:
<?xml version="1.0" encoding="utf-8" ?> <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <pipelines> <renderField> <processor patch:instead="processor[@type='Sitecore.Pipelines.RenderField.GetMemoFieldValue, Sitecore.Kernel']" type="Sitecore.Sandbox.Pipelines.RenderField.GetRawMemoFieldValueWhenApplicable, Sitecore.Sandbox"> <DefaultGetMemoFieldValueProcessor type="Sitecore.Pipelines.RenderField.GetMemoFieldValue, Sitecore.Kernel" /> </processor> </renderField> </pipelines> </sitecore> </configuration>
Let’s test this.
I added the “omitHtmlBreaks” parameter to the control I had shown above:
<%@ Control Language="c#" AutoEventWireup="true" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %> <sc:Text ID="scJavaScript" Field="JavaScript" Parameters="omitHtmlBreaks=true" runat="server" />
When I loaded my page, I was given a warm welcome:
When I viewed my page’s source, I no longer see HTML breaks:
If you have any thoughts on this, or know of another way to do this, please share in a comment.
we used asp:Literal control to render the MLT field value to prevent line-breaks,but this approach is better anyway!!
Hi Mike,
I’ve created a RawFieldRenderer control for this purpose:
public class RawFieldRenderer : FieldControl
{
protected override void DoRender(System.Web.UI.HtmlTextWriter output)
{
Item item = GetItem();
if (item != null && Field != null && !item.IsFieldNullOrEmpty(Field))
{
output.Write(item[Field]);
}
}
}
(IsFieldNullOrEmpty is a little extension method that checks if the field exists and contains any data)
I like the omitHtmlBreaks param idea as well. Literals are okay too, but require code-behind.
Hi
An alternative for writing all that code you could do this:
<sc:fieldrenderer runat="server" FieldName="hesting" Parameters='’ />
Remember to call DataBind() in your code behind or above the fieldrenderer.
This will not work since the “linebreaks” parameter is in the RenderParameters dictionary, not Parameters on the args instance.
Try it out. It works on my Sitecore 7 instance.
I will give it a go.
Thanks!
Mike
I got curious after your comment. My code works because of the SetParameters pipeline in renderField which contains a function called MoveLineBreaksParameterToRender. Check it out!
setParameters pipeline = setParameters processor
Ah ha! Another great find!
Thanks again!
Mike
I got your solution working!
Thanks again!
Mike
Haha, the “MoveLineBreaksParameterToRender” function. That doesn’t sound hacky *at all*.
But seriously, it might be a little dangerous depending on an undocumented feature like this, which may or me not be removed in future versions. But then again, it does work and without any code. It’s a cool find, in any case.
I’m sure it’s safe to use this undocumented feature. It’s in Sitecore 6 and Sitecore 7, so I’m pretty sure it’s going to be in Sitecore 8 unless they break their API.
Seems like there a problem showing code…
Inside parameters you should write: <%# “line-breaks=\n” %>
if not > and < is shown correctly they should be replaced with > and <
Hosted WordPress strips these, and I cannot control this functionality.
Please use their HTML entities in comments.