Using Data-* attributes with Sitecore MVC

If you’ve ever tried to use the data-* attributes in Sitecore you’ve noticed a discrepancy between how Sitecore and the default Html helpers work. Sitecore doesn’t appear to natively support supplying data_* attributes to “parameters” in any of its helpers (I take that back, you can supply them, they just don’t work like you’d expect).

To exemplify, assume you wanted to create a link that perhaps was wired up using KnockoutJS. You may have something like the following:

<a href="/" data-bind="click:SomeAction">Click Me</a>

In MVC, this might looks like the following:

@Html.RouteLink("Click Me", "Sitecore",
    /*routeParameters*/ null,
    /*htmlAttributes*/ new { data_bind = "click:SomeAction" })

In Sitecore, you’d use the Html.Sitecore() helpers. So let’s try mocking the above using the field “Link” (General Link) off our current item:

@Html.Sitecore().Field("Link",
    /*item*/ Sitecore.Context.Item,
    /*parameters*/ new { data_bind = "click:SomeAction" })

The output:

<a href="/">Home</a>

Wait, what just happened?

Sitecore doesn’t understand the data_* attributes like MVC does. MVC realizes that you cannot use keywords/symbols in object names, so it allows you to supplement hyphens with underscores. (Though, if you were really determined to use hyphens, you could also use the IDictionary<string,object> htmlParameters signature overload.)

Sitecore, however, doesn’t understand this (nor does it have a signature overload), so it simply forwards it along as an attribute (exempt of recognized parameters, e.g. “mw” and “mh” when rendering an Image).

The solution? Well, one of the many things I love about Sitecore is even if something doesn’t behave the way you want it to, it’s so customizable that you’re never really stuck. The work-around would be to create a custom process within the renderField pipeline which will allow us to work with these data_* attributes.

First step, create the custom renderField process for the pipeline:

using Sitecore.Diagnostics;
using Sitecore.Pipelines.RenderField;

public class SetDataParameters
{
    public void Process(RenderFieldArgs args)
    {
        Assert.ArgumentNotNull(args, "args");

        // Locate existing "data_* attributes
        var dataAttriubutes = args.Parameters
            .Where(x => String.Compare("data_", 0, x.Key, 0, 5, true) == 0)
            .Select(x => x.Key)
            .ToList();

        // Iterate over them and re-assign them as data-* attributes
        foreach (var originalDataAttribute in dataAttriubutes)
        {
            String reformattedDataAttribute = originalDataAttribute.Replace("_", "-");
            args.Parameters.Add(reformattedDataAttribute, args.Parameters[originalDataAttribute]);
            args.Parameters.Remove(originalDataAttribute);
        }
    }
}

Next, use a config include and register it:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <renderField>
        <processor patch:before="*" type="MySitecoreProject.Pipelines.RenderField.SetDataParameters, MySitecoreProject" />
      </renderField>
    </pipelines>
  </sitecore>
</configuration>

Now we can continue to supply data_* in the helpers and it will be correctly translated into its hyphenated counterpart. Hope that helps, and if you’ve run into a similar issue leave me a comment.

Flattr this!

Brad Christie

Software programmer from New Hampshire who enjoys the challenge and fulfillment of accomplishing any size task with ingenuity and persistence. I currently work at Sitecore as a Solutions Architect and an MVC evangelist.