In the previous post we talked about What Glass Mapper is and How to Use it. In this post I will talk about What’s New and Changed in Glass Mapper 5. You can find a demo solution here. This series on Glass Mapper has been presented at the Atlanta Sitecore User Group and SUG Chennai by me and my colleague Courtney Dean.
Major Changes at a Glance
- Changes to NuGet packages
- SitecoreContext, GlassView, GlassController are obsolete
- New contexts: IMvcContext, IRequestContext, IWebFormsContext
- SitecoreService methods parameters updates
- Changes to LazyLoading
- A new way of loading Glass configurations when working with Helix
We have covered the changes to NuGet in the previous post, which can save you some hassle if you accidentally forgot to reference sitecore.kernel and sitecore.mvc in your projects.
Obsolete Features
ISitecoreContext, GlassView, GlassContoller are obsolete. You don’t need them any longer. ISitecoreContext was responsible for a mixture of database access and request context. It is replaced with three new Contexts now available (IMvcContext, IRequestContext, IWebFormsContext), as they have much clearer separation of responsibilities and fit closer with Sitecore Architecture.
Any value GlassView and GlassController were providing is available through other means. One of the major function of GlassController, for example, was providing access to SitecoreContext, which is obsolete in the new version. Previously you were getting datasource or rendering parameters off the Glass Controller. Now you can get those from MvcContext.
GlassView allowed you to use helper methods in you .cshtml files to work with the Experience Editor without requiring to specify the model as it implicitly knows about the model property. However it has not been compulsory to use GlassView since V4 and we can access the same features using Html helpers such as Html.Glass.Editable().
Please note, these obsolete features will be removed eventually, so when you move to Glass Mapper 5 please get rid of them soon!
IMvcContext
This is The first one of the three contexts V5 offers, it’s also probably the one you will be working the most with . You used IMvcContext when you are working with MVC, and it’s mainly for Controlling Renderings. This context provides access to DataSourceItem, PageContextItem, RenderingItem, and RederingParamteres. Under the hood, it uses SitecoreService to talk to sitecore. You have seen some examples in the previous post but you can see the full demo solution here.
IRequestContext
You use Request Context when you are outside of a controller and do not have a DataSource item available. Common scenarios to use RequestContext include computed fields, pipeline processors, and event handlers. You can get ContextItem, HomeItem the RootItem from this context.
You used to have to get these properties and methods from GlassController and not be able to use it elsewhere. With IRequestContext you can inject the service to wherever you need. However, according to the experience of my colleague @SiteCorey, you should never inject it to a pipeline processor, as Sitecore has a bug and will break your code. Instead use Service Locator and you can see an example of that in the demo.
If you take a look at the demo solution you can see (shown below) these services are registered to the container as Scoped – so all contexts use the same instance of SitecoreService and don’t have to create new ones within a Request. SitecoreService is registered using Context.Database, but if you need to access the core database you can create a new SitecoreService for core.
public class GlassMapperConfigurator : IServicesConfigurator { public void Configure(IServiceCollection serviceCollection) { serviceCollection.AddScoped<ISitecoreService>(sp => new SitecoreService(Context.Database)); serviceCollection.AddScoped<IMvcContext>(sp => new MvcContext(sp.GetService<ISitecoreService>())); serviceCollection.AddScoped<IRequestContext>(sp => new RequestContext(sp.GetService<ISitecoreService>())); serviceCollection.AddScoped<IWebFormsContext>(sp => new WebFormsContext(sp.GetService<ISitecoreService>())); } }
Same as IMvcContext, this Context uses SitecoreService to communicate with Sitecore.
IWebFormContext
DO NOT USE WEBFORMS!
Changes to ISitecoreService
Quoting from the Glass documentation: “The ISitecoreService interface represents an individual Sitecore database. It provides the ability to perform all basic CRUD functions against the selected Sitecore databases.” Essentially it is a wrapper for a Sitecore database. A common useful scenario is to access the core database.
The big change in V5 is the method parameters of SitecoreService have been replaces with Option classes which allow for configuring all settings for model mapping. This change is because parameters were limiting, every time a parameter was added there would be a ton of overloads added to handle the various situations. Using Options classes allows the ability to add additional configuration without having to change the signature of the method. The old way of passing parameters is still available but is being marked obsolete.
Here is a list of types of Options classes:
- – `GetItemByIdOptions`
- – `GetItemByItemOptions`
- – `GetItemByPathOptions`
- – `GetItemByQueryOptions`
- – `GetItemOptions`
- – `GetItemOptionsParams`
- – `GetKnownOptions`
Alternatively you can use two parameters, with the second one being a configuration map for the attributes you want to include. As an example, what used to be:
sitecoreService.GetItem("/sitecore/Home", inferType:true);
can now be:
service.GetItem("/sitecore/Home",x=>x.InferType());
The attributes can be:
- InferType
- Lazy
- Cache
- EnforceType
- TemplateId
- Version
- Language
LazyLoading
The LazyLoading attribute has been removed from all property configurations (both attribute and fluent). You can now add the attribute when requesting a model from SitecoreService or when getting the datasource from MvcContext.
Previously you had to manually turn LazyLoading off on each property of the model. Now you add the attribute when you are getting the item from SitecoreService or a context, then all properties will be set accordingly.
Here is an example using SitecoreService:
var service = new SitecoreService(database.Database); var target = service.GetItem<IModel>("/sitecore/content/parent/target", x=>x.LazyDisabled());
And an example using MvcContext (note the GetKnownOptions which is a new Glass 5 feature mentioned above):
var dataSource = _mvcContext.GetDataSourceItem<DemoArticle>(new GetKnownOptions { Lazy = Glass.Mapper.LazyLoading.Disabled});
LazyLoading is on by default – unless caching is on.
Working with Helix – the Newest Update in V5.1 Oct 10th
As mentioned in the previous post, if you are working with a Helix solution, GlassMapper.Sc should be only installed in an ORM project in the Foundation layer, i.e., the two files generated when installing the main NuGet package should live in the app_start folder in this module.
In Feature and Project layer projects Glass.Mapper.Sc.Core always needs to be installed. Install Glass.Mapper.Sc.Mvc only when needed – when working with MVC and need access to MvcContext.
As mentioned previously, any custom configurations needs to be added to the GlassMapperScCustom.cs file, which lives in the foundation layer. Doing this not only brings the risk of having the custom configuration overwritten when upgrading Glass, but also brings to the solution backward dependency from Foundation layer to Feature layer, which violates Helix principles. In Helix Foundation modules can only reference other Foundation modules; they may not reference Feature modules or project modules.
In V5.1, a new way to load configurations is introduced. Instead of adding the configurations into the custom file in Foundation layer, it can be added using a new Sitecore pipeline. You can find some example code snippet here. Specifically, create a processor that inherits GetGlassLoadersProcessor in the feature module that you are working with and need custom Glass configuration for. The configurations is added to this processor. Then add this processor to the glassMapper.getGlassLoaders pipeline. Thus the Foundation ORM module doesn’t reference and isn’t dependent on your Feature layer. In addition, since there is no need to edit GlassMapperScCustom.cs file – there is no risk of getting it overwritten when upgrading Glass. One stone, two birds.
You can find out more here…