Use Dependency Injection to resolve Sitecore View Rendering Models with Glass Mapper

In Sitecore MVC, a view rendering consists of a (Razor) view and optionally a model. The model has a definition item under /sitecore/layout/Models and must be referenced in the field Model of the rendering definition item. Now when Sitecore is loading a view rendering, it starts the pipeline mvc.getModel to create an instance of the referenced model and passes the model to the view. By default Sitecore creates the model instance with Activator.CreateInstance(), which means that the class needs a default constructor and doesn't allow constructor injection. John West has written a good blog post here how you can use dependency injection to create the model.

But what is different when you use Glass Mapper? Glass Mapper adds a new processor GetModelFromView.cs in the mvc.getModel pipeline which resolves the model automatically out of the model definition in the view (@model xyz). The model definition item under /sitecore/layout/Models and the reference in the rendering definition item are not needed anymore. Wohhooo! But this also means, that the approach from John West to create models using dependency injection doesn't work anymore. Fortunately Glass Mapper is almost as flexible than Sitecore itself, so there is a way too.

Glass Mapper has a concept called Object Construction pipeline. This is not a Sitecore pipeline, but works similar. There are different tasks in this pipeline and each task is responsible to create an object. When resolving the model from the view rendering, the model instance is also created using this pipeline. So the only thing we need to do is adding a new task to resolve our model with our dependency injection container. A task must always implement the interface IObjectConstructionTask. In the following example I have added an empty interface IContainerModel to identify which models I want to resolve using the container. All models in my view renderings which should be resolved using dependency injection must implement the interface IContainerModel as well. The task itself is very simple:

public class CreateViewModelTask : IObjectConstructionTask
{
    public virtual void Execute(ObjectConstructionArgs args)
    {
        // check that no other task has created an object and that this is a model which should be resolved using the container
        if (args.Result != null || !typeof(IContainerModel).IsAssignableFrom(args.Configuration.Type)) return;

        // create instance using the container
        var model = MyContainer.Resolve(args.Configuration.Type);

        // set the new object as the returned result
        args.Result = model;
    }
}

The task needs to be registered in Glass Mapper and it's important that this task runs first. Otherwise it will result in a similar exception than in the beginning that there is no default constructor available. With Glass Mapper V4 the task can be registered in GlassMapperScCustom.cs while initializing Glass Mapper:

public static IDependencyResolver CreateResolver()
{
    var config = new Glass.Mapper.Sc.Config();
    var dependencyResolver = new DependencyResolver(config);

    // register the task at index 0 (first)
    dependencyResolver.ObjectConstructionFactory.Insert(0, () => new CreateViewModelTask());

    return dependencyResolver;
}

That's it. Summarized this has the following advantages:

  • You don't need to create a model definition item in Sitecore anymore, just define the model type in your view and let Glass Mapper handle the rest.
  • All your models will automatically be resolved using your prefered dependency injection container.
  • You can control which models should be resolved using your container with the interface IContainerModel.

Do you already use this feature from Glass Mapper? Are there any other ways to have similar results?

Kevin Brechbühl

Senior Developer & Architect | C# & ASP.NET | Sitecore Technology MVP

comments powered by Disqus