smithsson68@gmail.com
Apr 7, 2011
  6227
(1 votes)

Providing a custom view for your Visitor Group criteria

In this blog post, Magnus Paulsson shows us a nice example of creating a criterion for the EPiServer Visitor Group framework and making the UI richer with the use of DoJo and MVC controllers. In this post I would like to show you how you can provide your own custom view for a criterion to plug-in to the Visitor Group Admin.

The Visitor Group Admin user interface is MVC 2.0 based and therefore uses convention over configuration. What that means is that you don’t use web.config or code based attributes to register a Visitor Group Admin criterion view like you would for other types of EPiServer CMS view plug-ins. Where the view is placed in the site’s structure and what it is called are the conventions that make it work.

So for example, to provide a custom view for Magnus’ example, you would create a typed MVC Partial View, the View Data class is the Visitor Group model, in this case:

ACME.Personalization.VisitorGroups.Criteria.RoleModel

The view should be given the same name as the model:

RoleModel.ascx
image

and it should be placed in the following folder structure in the site:

image

Now when an instance of the criterion is added to a Visitor Group in Visitor Group Admin, the custom view will be shown instead of the default one.

Of course you may use any HTML you like in your custom view but the EPiServer Visitor Group framework adds some extension methods to the System.Web.Mvc.HtmlHelper instance that can be used. The extension methods help you render the edit control html for your model’s properties leaving you free to concentrate more on the overall layout.

In Magnus’ example his model has 2 properties:

[DojoWidget(
SelectionFactoryType = typeof(EnumSelectionFactory),
LabelTranslationKey = "/shell/cms/visitorgroups/criteria/role/comparecondition",
AdditionalOptions = "{ selectOnClick: true }"),
Required]
public RoleCompareCondition Condition { get; set; }

[DojoWidget(
LabelTranslationKey = "/shell/cms/visitorgroups/criteria/role/rolename",
AdditionalOptions = "{ selectOnClick: true }"),
Required]
public string RoleName { get; set; }

The Condition property is decorated with the DojoWidget attribute and the SelectionFactoryType property is set. In this case the EPiServer Visitor Group framework will render a dijit.form.FilteringSelect control by default. In your custom view you can render the default edit control for the property by calling one of the DojoEditorFor extension methods provided:

<%= Html.DojoEditorFor(model => model.Condition)%>

There are 5 overloads of the DojoEditorFor method available:

/// <summary>
/// Creates Dojo editor.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <param name="html">The HTML helper.</param>
/// <param name="p">The property.</param>
/// <param name="htmlAttributes">Additional html attributes</param>
/// <param name="label">The label text.</param>
/// <param name="labelCssClass">Css class for the label</param>
/// <param name="labelPosition">The position of the label relative to the editor control</param>
/// <returns>The rendered HTML markup</returns>
public static MvcHtmlString DojoEditorFor<TModel>(this HtmlHelper<TModel> html, PropertyInfo propertyInfo, object htmlAttributes, string label, string labelCssClass, LabelPosition labelPosition)

/// <summary>
/// Creates Dojo editor.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="html">The HTML helper.</param>
/// <param name="expression">The property expression.</param>
/// <param name="htmlAttributes">Additional html attributes</param>
/// <param name="label">The label text.</param>
/// <param name="labelCssClass">Css class for the label</param>
/// <param name="labelPosition">The position of the label relative to the editor control</param>
/// <returns>The rendered HTML markup</returns>
public static MvcHtmlString DojoEditorFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes, string label, string labelCssClass, LabelPosition labelPosition)

/// <summary>
/// Creates Dojo editor.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="html">The HTML helper.</param>
/// <param name="expression">The property expression.</param>
/// <param name="htmlAttributes">Additional html attributes</param>
/// <param name="label">The label text.</param>
/// <param name="labelCssClass">Css class for the label</param>
/// <returns>The rendered HTML markup</returns>
public static MvcHtmlString DojoEditorFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes, string label, string labelCssClass)

/// <summary>
/// Creates Dojo editor.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="html">The HTML helper.</param>
/// <param name="expression">The property expression.</param>
/// <param name="htmlAttributes">Additional html attributes</param>
/// <returns>The rendered HTML markup</returns>
public static MvcHtmlString DojoEditorFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes)

/// <summary>
/// Creates Dojo editor.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="html">The HTML helper.</param>
/// <param name="expression">The property expression.</param>
/// <returns>The rendered HTML markup</returns>
public static MvcHtmlString DojoEditorFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)



 

The custom view for Magnus’ Visitor Group criterion model could look something like this:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ACME.Personalization.VisitorGroups.Criteria.RoleModel>" %>
<%@ Import Namespace="EPiServer.Personalization.VisitorGroups" %>
<div class="somefancyclassthatmakesthislookreallycool">
    <div>
        <%= Html.DojoEditorFor(model => model.Condition)%>
    </div>
    <div>
        <%= Html.DojoEditorFor(model => model.RoleName)%>
    </div>
</div>

Of course you don’t need to use the DojoEditorFor methods. You can ride roughshod over the model’s user interface demands and render the edit user interface however you like. However, there is a big chance of problems here as the edit controls you use must be compatible with the dijit controls the Visitor Group framework is expecting for the property. For example, given a model class like this:

public class TestCriterionModel : CriterionModelBase
{
    public string SomeStringValue { get; set; }
    public int SomeIntValue { get; set; }
    public bool SomeBoolValue { get; set; }

    public override ICriterionModel Copy()
    {
        return base.ShallowCopy();
    }
}

you could define your view using your own HTML for the edit controls as follows;

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<EPiServer.TestCriterionModel>" %>
<div>
    <div>
        <input type="text" id="SomeStringValue" />
    </div>
    <div>
        <input type="text" id="SomeIntValue" />
    </div>
    <div>
        <input type="text" id="SomeBoolValue" />
    </div>
</div>

and it works quite happily:

image

However, as you can see the dijit styles used by the Visitor Group framework have been applied to the controls and they no longer look like plain <input> controls any more. So the point here is to use the DojoEditorFor extension methods where possible to render the edit controls and if some reason you don’t want to then expect to get into some javascript to fight against what the Visitor Group framework does.

By using a combination of custom views and the Dojo Javascript Framework you can really personalize the Visitor Group Admin user inteface.

Happy customizing!

Apr 07, 2011

Comments

Magnus Rahl
Magnus Rahl Apr 8, 2011 09:00 AM

Nice! Have to find time to try it out :)

May 22, 2017 10:39 PM

Please login to comment.
Latest blogs
Plug-in manager is back in CMS 12

Plug-in manager is back in the UI, what is it and how can i use it?

Luc Gosso (MVP) | Oct 6, 2022 | Syndicated blog

Display Child Pages in Content Delivery API Response

The below example will implement an instance of IContentConverterProvider to customise the serialisation of PageData and output child pages in the...

Minesh Shah (Netcel) | Oct 4, 2022

Bring the Report Center back in Optimizely CMS 12

The Report Center has been a part of Optimizely CMS since its first debut in version 5R2 in 2008, but in CMS 12, it's removed! Don't despair! Make...

Tomas Hensrud Gulla | Oct 4, 2022 | Syndicated blog

Customizing Property Lists in Optimizely CMS

Generic property lists is a cool editorial feature that has gained a lot of popularity - in spite of still being unsupported (officially). But if y...

Allan Thraen | Oct 2, 2022 | Syndicated blog