I’ve been having(and still) the great pleasure to work with Glass.Mapper for Sitecore and I must say it makes your life so much easier as a developer. Mike Edwards, the founder has done one heck of a job ๐
I really like the interface model approach where you let an interface represent a sitecore item.
This is a quick post regarding rendering parameters and mapping them to a viewmodel.
In Glass.Mapper when using(inheriting) the GlassController you will find some very nifty methods like GetDataSourceItem and GetRenderingParameters.
Let’s say you have following rendering parameters in Sitecore:
This is how it will be represented as an interface
[SitecoreType(TemplateId = "{here is a template id}", AutoMap = true)] public interface IVisibilityRenderingParameters { bool VisibleOnDesktop { get; set; } bool VisibleOnTablet { get; set; } bool VisibleOnMobile { get; set; } }
To get the rendering parameters in your Action Result you just have to call the GetRenderingParameters method(You need of course inherit the GlassController to your controller).
IVisibilityRenderingParameters renderingParameters = GetRenderingParameters<IVisibilityRenderingParameters>();
That is very nice and so easy to use.
Now what I would like to do is to add(map) the parameters to my interface viewmodel. Here is the viewmodel representing a news spot item:
[SitecoreType(AutoMap = true)] public interface INewsSpotModel : IVisibilityRenderingParameters { string Header { get; set; } string Subheader { get; set; } Image BackgroundImage { get; set; } }
As you can see I’m inheriting the IVisibilityRenderingParameters.
What will happen when I call the GetDataSourceItem(which is also from the GlassController) for the viewmodel INewsSpotModel?
INewsSpotModel model = GetDataSourceItem<INewsSpotModel>();
Well the tree properties from IVisibilityRenderingParameters will not be set, but…
What if we could do something like this and get the data from the rendering parameters to the viewmodel
INewsSpotModelmodel = GetDataSourceItemWithRenderingParameters<INewsSpotModel, IVisibilityRenderingParameters>();
I’ve added a generic method to our controller(best would be if you had a base controller which of course needs to inherit the GlassController).
using AutoMapper; using Glass.Mapper.Sc.Web.Mvc; namespace Sandbox.Website { public class MyBaseController : GlassController { /// <summary> /// Map rendering parameters to datasource item interface. /// </summary> /// <typeparam name="TModel">Datasource item interface</typeparam> /// <typeparam name="TRenderingParameters">Rendering parameters interface</typeparam> /// <param name="isLazy"></param> /// <param name="inferType"></param> /// <returns></returns> protected TModel GetDataSourceItemWithRenderingParameters<TModel, TRenderingParameters>(bool isLazy = false, bool inferType = false) where TModel : class where TRenderingParameters : class { TModel model = GetDataSourceItem<TModel>(isLazy, inferType); TRenderingParameters parameters = GetRenderingParameters<TRenderingParameters>(); //If no parameters if (parameters == null) return model; Mapper.Initialize(cfg => cfg.CreateMap<TRenderingParameters, TModel>()); model = Mapper.Map(parameters, model); return model; } } }
We will get the viewmodel(TModel) item using the GetDataSourceItem method and to get the rendering parameters(TRenderingParameters) we use the GetRenderingParameters method.
Now to map the rendering parameters to the viewmodel we will use AutoMapper. In the Mapper.Initialize method we will set the mapping configurations and it’s all generic ๐
Mapper.Initialize(cfg => cfg.CreateMap<TRenderingParameters, TModel>());
The actual mapping happens in this line:
model = Mapper.Map(parameters, model);
To make it even prettier we could move the mapping configuration(and initializing) to a dependency injection container. But then we will have to specify what viewmodel is using/inheriting rendering parameter model and so on.
I’m not sure if we could use something from Glass.Mapper instead, I mean there is AutoMap().
Thatโs all for now folks ๐
Interesting read and I wish I had implemented something similar in my last project, It used plenty of Rendering Parameter templates.
I think you are right with regards to finding a Glass way of mapping instead of the AutoMapper .Map but I’m not sure how you would. I would also be interested in finding out more about the Mapping and Initialization via a DI.
One final observation, on the TModel constraint don’t you need to specify TRenderingParameters as the base type ?
LikeLiked by 1 person
Hey Mark
Thanks for reading ๐
You know what? With the latest Automapper you don’t need to do this anymore:
Mapper.Initialize(cfg => cfg.CreateMap());
Just this(If you have it as DI):
model = Mapper.Map(parameters, model);
Pretty neat ๐
About specify base type for TRenderingParameters, I use class
At the end of the method:
TRenderingParameters : class
LikeLike