Windsor Construction

This tutorial applies only to Glass.Mapper.Sc V3.

With Glass you can turn on Castle Windsor construction so that your models are instantiated by the Castle Windsor container. You might ask why you would want to do this, well it allows you to combine services with data mapped from Sitecore in one call.

To demo this I am going to create a landing page that lists out RSS feed items. I want the URL to the RSS feed to specified in Sitecore along with the number of articles I want to display. My model will look like this:

using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Syndication;
using Glass.Mapper.Sites.Sc.Services.BbcNews;

namespace Glass.Mapper.Sites.Sc.Models.Landing
{

    public class RssLanding
    {
        private readonly IRssService _service;

        public virtual string RssUrl { get; set; }

        public virtual int Number { get; set; }

        public virtual string Title { get; set; }

        public RssLanding(IRssService service)
        {
            _service = service;
        }

        public IEnumerable<SyndicationItem> GetArticles()
        {
            var result = _service.GetArticles(RssUrl);
            return result.Take(Number);
        }
    }
}

Notice that the constructor on my model takes an RSS Service, I need to get Castle Windsor to load this service and also tell Glass.Mapper to use the Windsor Construction. We need to update the GlassMapperScCustom class in the App_Start folder, first we create an instance of the Config class and set the UseWindsorConstructor property to true:

    var config = new Config();
    config.UseWindsorContructor = true;

Now we pass our Config class into the SitecoreInstaller and we also need to load our new service in to the Windsor Container. I have used a Windsor Installer  to load my RssService class but you could do this without the installer:

    //create the resolver
    container.Install(new SitecoreInstaller(config));
    container.Install(new ServiceInstaller());

The Windsor Installer:

using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using Glass.Mapper.Sites.Sc.Services.BbcNews;

namespace Glass.Mapper.Sites.Sc.App_Start
{
    public class ServiceInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(
                    Component.For<IRssService>().ImplementedBy<RssService>().LifestyleTransient()
                );
        }
    }
}

I now have my container setup and Glass.Mapper ready to use, lets look at the sublayout code:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="RssLandingSublayout.ascx.cs" 
    Inherits="Glass.Mapper.Sites.Sc.layouts.Site.Landing.RssLandingSublayout" %>
<h2><%=Model.Title %></h2>

<ul class="thumbnails">
    <% foreach (var article in Model.GetArticles())
       { %>
    <li class="span4">
    <div class="thumbnail">
      <h3><a href="<%=article.Links.First().Uri.ToString() %>"><%=article.Title.Text %></a></h3>
      <p><%=article.Summary.Text %></p>
    </div>
  </li>
    <% } %>
</ul>

using Glass.Mapper.Sc.Web.Ui;
using Glass.Mapper.Sites.Sc.Models.Landing;

namespace Glass.Mapper.Sites.Sc.layouts.Site.Landing
{
    public partial class RssLandingSublayout : GlassUserControl<RssLanding>
    {
    }
}

My sublayout still remains really simple, the loading of the model and its dependency on the RssService is all handled by Glass.Mapper.

Finally in Sitecore I just need to set the RSS URL and number or articles to display:

Once we publish everything and load the page we can see the RSS feed items rendered:



Currently you cannot mix Castle Windsor constructor injection with Glasses standard constructor injection.

In this tutorial we have seen how you can enable the Castle Windsor construction to allow you to create a class that contains both Sitecore data and service in a single call.