Both Sitecore and ASP.NET MVC both provide a development model that allows for distinct boundaries to be created between data, application logic, and presentation logic. The purpose of this post is to describe the manner in which these capabilities can be utilized within a Sitecore MVC solution to provide content authors with the ability to customize the appearance of presentation components. The implementation of these capabilities involves configuration within Sitecore, creation of enablement code, and implementation of front end display logic to honor the configured parameters.
Rendering Parameters
Sitecore provides for the clear separation between the data which will be displayed and the details of how it will be displayed on different devices through the use of Presentation Layout Details. The Presentation Layout Details allows the content author to configure which layouts and renderings will be utilized when presenting any given content item to the end user. In addition to specifying which layouts and renderings will be used, the individual presentation components can each be further configured using the Parameters field, which is is designed to accept key/value pairs in a querystring format (such as “showBorder=true&margin=20px”) and passes these values to the rendering components as contextual data at runtime. This functionality serves as the basis for the overall solution for configurable views.
Rendering Parameter Templates
The benefit of being able to pass user defined information to renderings at runtime is somewhat offset by the need for the content author to know which key/value pairs will have some sort of meaning to the code performing the rendering at runtime and the range of expected values for each key. With a non-trivial number of renderings and parameters, this quickly becomes unmanageable to the point where rendering parameters seem like they would not be a viable solution. Sitecore provides resolution for this drawback in the form of Rendering Parameter Templates, which allow the template author to specify named parameters which will appear in the dialogue used to configure presentation component properties and the data type of these parameters. Because the parameter names and value data type are specified by the template author, the potential for errors due to incorrectly keyed information is greatly reduced and the use of rendering parameters to control dynamic rendering behavior once again becomes feasible and even desirable.
Creating a Rendering Parameter Template
The key to creating a Rendering Parameter Template is to derive the template from the following template:
/sitecore/templates/System/Layout/Rendering Parameters/Standard Rendering Parameters
This inheritance ensures that the default parameter fields such as those related to the placeholder and caching options are present and then allows you to create your own fields just as with any other data template.
For good discoverability, Rendering Parameter Templates should be named in a manner that clearly identifies the purpose of their parameters and should be logically grouped within the content tree. Here are some examples of parameter templates named in an intuitive manner:
- Add Margin Rendering Template Parameters
- Show Separator Rendering Template Parameters
- Add Margin and Separator Rendering Template Parameters
Assigning a Rendering Template to Presentation Components
Once a rendering template has been created, it can be attached to a presentation component (e.g. rendering, layout, sublayout) by updating the “Parameters Template” field of the presentation component’s definition. It is important to note that the Parameters Template field is a droplink field which only allows for the selection of a single value. This is the reason that multiple inheritance must be used to create a composite template when options from more than one rendering template are desired (as was done with the “Margin and Divider Rendering Template Parameters” template shown in the previous section).
Configuring a Presentation Component Instance
Having assigned a Rendering Parameters Template to a presentation component, content authors will now have the option to assign values to the fields defined in the Rendering Parameters Template by navigating to the Presentation Layout Details of a content item and then selecting the presentation component for which they want to configure rendering parameters. The content author will be presented with appropriate controls for the parameters’ data type to help ensure that they enter appropriate data.
Enablement Code
Accessing the configured rendering parameters at runtime does not require complex code, but the code is also non-trivial and duplication should be avoided when possible, so common code to be utilized by views should be added to your Sitecore MVC solution. The functionality can been exposed through two methods added to a helper class. The following sections describe the methods.
GetValueFromCurrentRenderingParameters
This method is responsible for interacting with the current rendering context to retrieve the value of the parameter with the specified name. If the parameter does not exist or the current rendering context is unavailable, the method will return null. It should be noted that this method works around a problem with in Sitecore’s RenderingParameters constructor (at least in the 6.6 release preview) where certain parameters querystring values cause a “null key” exception by bypassing the Parameters property by instead retrieving the field’s raw value from the Properties collection and parsing from there. The following code shows a sample implementation of this method:
public static string GetValueFromCurrentRenderingParameters(string parameterName) { var rc = RenderingContext.CurrentOrNull; if (rc == null || rc.Rendering == null) return (string)null; var parametersAsString = rc.Rendering.Properties["Parameters"]; var parameters = HttpUtility.ParseQueryString(parametersAsString); return parameters[parameterName]; }
GetItemsFromCurrentRenderingParameters
Rendering parameters use the same data types as any other data template, but the enhanced lookup functionality of field types such as droplink and multilist do not apply, so code that consumes these parameters must interact with Sitecore more directly to parse item ids and retrieve the associated items. This method abstracts the required steps and returns an array of Item objects represented by the field value. If no items are represented by the field value, an empty array is returned as opposed to null, so the return can always be safely used in enumeration (such as a foreach loop). The following code shows a sample implementation of this method:
public static Item[] GetItemsFromCurrentRenderingParameters(string parameterName) { List result = new List(); var rc = RenderingContext.CurrentOrNull; if (rc != null) { var itemIds = GetValueFromCurrentRenderingParameters(parameterName) ?? string.Empty; var db = rc.ContextItem.Database; var selectedItemIds = itemIds.Split('|'); foreach (var itemId in selectedItemIds) { Guid id = Guid.Empty; if (Guid.TryParse(itemId, out id)) { var found = db.GetItem(new ID(id)); if (found != null) { result.Add(found); } } } } return result.ToArray(); }
Consuming Rendering Parameters from View Code
In addition to making rendering parameters available at runtime, views must be updated to do something with these parameters. The ideal case calls for retrieval of the parameter and either directly injecting the parameter value into markup or performing extremely simple logic to derive a value. The following snippet illustrates code that retrieves a multilist value from the rendering parameter and emits the names of the configured items as space separated CSS class names in the markup that is sent to the browser:
@{ var marginCssClass = string.Empty; var marginItems = myHelper.GetItemsFromCurrentRenderingParameters("Margin"); if(marginItems.Length > 0) { marginCssClass = string.Join(" ", marginItems.Select(i => i.Name).ToArray()); } } <section class="@marginCssClass">
For an example of parameters that require simple logic to be performed, the following sample illustrates the use of a checkbox field typed parameter to determine whether a CSS class should be appended to the container for a rendering:
@{ string showSeparator = myHelper.GetValueFromCurrentRenderingParameters("showSeparator"); string containerClass = showSeparator == "1" ? "seperated" : string.Empty; } <section class="@containerClass">
As a general practice, using rendering parameters to control whether and which CSS classes are emitted is an effective control to help ensure that the rendering parameters are being used purely for presentation logic as is their purpose. Use beyond that may include determining whether to omit specific sections of markup may also be a valid use, but this also may indicate that a view should be refactored into two renderings which may be used together. In any case, care must be taken to avoid business logic being executed based on rendering parameters because this violates fundamental principles of an MVC-based approach.
Summary
In this posting, I’ve discussed how rendering parameters and rendering parameter templates in Sitecore can be utilized to provide configurable views. You should now have an understanding for how these parameters can be leveraged in a Sitecore MVC to provide a flexible solution that allows for clear segregation of concerns.