Share

LinkedIn

Glass Mapper Model Binding

Decouple your Sitecore MVC controllers from Glass Mapper with a custom model binder.

When using Glass Mapper with Sitecore MVC, developers typically use View renderings. These views have their models populated by the processors provided by Glass for the getModel pipeline. This method works well for simple renderings that have no logic.

When a rendering requires additional logic before passing the model to the view, a controller is needed. Glass Mapper provides the GlassController base class which you can use to give your controller methods that will map your data source item and rendering parameters for you. Using that base class, however, couples your controller to Glass pretty tightly. Also, it leads to a lot of repetition in your action methods where you are just asking glass to give you some kind of model.

A cleaner solution would allow you to use normal views with a @model directive and normal controllers that derive directly from System.Web.Mvc.Controller. This goal can be achieved using a custom model binder. You can then just pass the Glass models into your action methods as parameters and they will be mapped for you and ready to go.

First, you need to create two interfaces. One will be implemented by all of your item models and the other by your rendering parameter models. If you use TDS code gen for Glass Mapper, you probably already have one called IGlassBase that will work well for the item models.

Next, you’ll need the model binders. The GlassItemModelBinder will attempt to map your model class from the rendering’s data source item, if there is one, or fall back to the context item. The GlassParametersModelBinder will map from the rendering parameters.

The GlassModelBinderProvider decides when those model binders should be used. It does this by checking to see if the model implements the interface for item models or rendering parameter models. The types that it checks for are passed in as constructor parameters.

Finally, a processor for the initialize pipeline creates an instance of the model binder provider and provides it with the types that it should use to determine the correct model binder for a given model.

When all of these pieces are in place, you can use a standard ASP.NET MVC controller and just pass your models to the action method as parameters like so:

public ActionResult Content(
    SampleItem dataSourceModel,
    SampleRenderingParameters parametersModel)
{
    var viewModel = new ContentViewModel
    {
        DataSource = dataSourceModel,
        Parameters = parametersModel
    };
 
    // Do more work
 
    return View(viewModel);
}

Nice and clean and easy to test.

If you want to view the full source or just grab the files for your project, you can get them at https://github.com/BenGGolden/GlassModelBinding.

Sitecore development, Sitecore custom code, Sitecore MVC

Comments

Add a Comment

*
*

Please confirm you are human by typing the text you see in this image:

Nathanael Mann said: 10/30/2015 at 4:44 AM

Interesting Article, not sure its an approach I would personally use since GlassController gives you helpers for rendering parameters and other stuff, but its definitely viable and a nice insight into model binding and the versatility Glass can provide solutions.

Glass recently did a lot of work to make your models more testable as well as giving typed GlassControllers which make life much easier on the testing front.

Ben Golden said: 10/30/2015 at 1:18 PM

This approach lets you get your rendering parameters via model binding as well. GlassController doesn't really provide much else except for properties for ContextItem and LayoutItem, which you can get straight from Sitecore using PageContext or RenderingContext. If you need to use Glass for more than just the standard data source & rendering parameter models, you can inject ISitecoreContext and/or IGlassHtml into your controller's constructor.

Also note that GlassController inherits from SitecoreController. Unless you are implementing a page-level controller, you probably don't need or want that. See: http://stackoverflow.com/a/14999263