Search code examples
c#genericssitecoresitecore7.2glass-mapper

Using a generic type in a Sitecore view rendering with Glass Mapper


Setup

Models

POCOs, virtual is required by Glass Mapper.

using System.Collections.Generic;
using Glass.Mapper.Sc.Configuration.Attributes;
using Glass.Mapper.Sc.Fields;

namespace Sample
{
    public class Parent<T>
    {
        [SitecoreId]
        public virtual Guid Id { get; set; }
        public virtual string Title { get; set; }
        public virtual IEnumerable<T> Children { get; set; }
    }

    public class Article
    {
        [SitecoreId]
        public virtual Guid Id { get; set; }
        public virtual string Title { get; set; }
        public virtual string Text { get; set; }
    }

    public class Teaser
    {
        [SitecoreId]
        public virtual Guid Id { get; set; }
        public virtual string Title { get; set; }
        public virtual Image Banner { get; set; }
    }
}

Views

Referenced by Sitecore as view renderings, with the model pointing to Sample.Parent (see below for Sitecore model definitions).

@inherits Glass.Mapper.Sc.Web.Mvc.GlassView<Sample.Parent<Sample.Article>>

<h1>@Editable(x => x.Title)</h1>
<div class="article-list">
    @foreach (var article in Model.Children)
    {
        <article class="article">
            <h2 class="article-title">@Editable(article, x => x.Title)</h2>
            <div class="article-content">@Editable(article, x => x.Text)</div>
        </article>
    }
</div>
@inherits Glass.Mapper.Sc.Web.Mvc.GlassView<Sample.Parent<Sample.Teaser>>

<h1>@Editable(x => x.Title)</h1>
<div class="teaser-list">
    @foreach (var teaser in Model.Children)
    {
        <article class="teaser">
            <h2 class="teaser-title">@Editable(teaser, x => x.Title)</h2>
            <div class="teaser-banner">@RenderImage(teaser, x => x.Banner)</div>
        </article>
    }
</div>

Sitecore model definitions

Here's where I'm not sure if I did it right. These are the model types I defined as the Sitecore models (under /sitecore/layout/models).

  • Sample.Parent`1[T], Sample

    Also tried (without success):

    • Sample.Parent, Sample
    • Sample.Parent`1[Sample.Article, Sample], Sample
    • Sample.Parent<Sample.Article>, Sample)
  • Sample.Article, Sample

  • Sample.Teaser, Sample

Is this possible?

The example code is simplified, but should capture what I'm trying to do. Basically I want to be able to use the generic type as a way to reuse more code. Because of external restrictions I'm unable to use anything but Glass Mapper 3. The errors I'm seeing are either that Sitecore cannot find the type, or a "object reference not set" (it appears to use Sitecore.Mvc.Presentation.RenderingModel, Sitecore.Mvc as a model when this happens).

Or am I being crazy? :) Is there a better way to accomplish this?


Solution

  • I think there is probably difficulties in the way that Glass tries to process the generic string (To be honest I never designed it to handle generic strings).

    If you are using V4 then you don't need to define a model in Sitecore. Leave the model field blank and Glass should resolve the model from the @inherits deceleration in the cshtml file.