It is very trivial to retrieve items from Sitecore content repository. Like any other CMS, Sitecore provides APIs for reading and enumerating items and item fields and there is nothing special about it. Without wasting time, let’s talk code straight away. Consider following two lines of code typically found in code behind of a SubLayout:
Sitecore.Data.Items.Item item = Sitecore.Context.Database.GetItem("/sitecore/content/home/products/tv"); if (item != null) { String title = item["Title"]; //Sharp 47.9" LED TV double price = Convert.ToDouble(item["Price"]); //1200 double size = Convert.ToDouble(item["Size"]);// 47.9 }
Assume the following data template inheritance:
Technically there is nothing wrong with above two lines of code and it is going to work as expected. However a production level Sitecore implementation typically has several items in its content tree and relationship among them is often anything but simple. Code similar to above isn’t intuitive until you read few lines and also it involves accessing fields through string constant. Having object oriented programming around us for several years, your first reaction would be to hide item under a logical entity, say class Product and then consume a Product instance so fields can be accessed through object properties in strongly typed fashion:
Television sharpLEDTV = new Television("/sitecore/content/home/products/tv/sharp47"); String title = sharpLEDTV.Title; double price = sharpLEDTV.Price;
The implementation of a sublayout may look something like this(see implementation code for Product and Television classes below. Details are omitted for brevity):
It is clearly better way of accessing an item and its fields for number of reasons:
- Loosely coupled implementation: as you see, view (.ascx file) and controller(.ascx.cs file) don’t reference Sitecore item as it is encapsulated within the model. It helps writing presentation and controller independently without mixing Sitecore items and fields into it. This is very helpful in a team of multiple developers where presentation is developed in parallel to data access logic.
- Extensibility and Testability: Separation of concerns adds flexibility to the implementation. If data access and/or mapping implementation changes, views and controllers don’t need to be updated. Such implementations are easily extensible. Models can be easily mocked to support development of views and controllers.
- Better readability – One can easily figure out that a product is being read, just by looking at first line.
- Strongly typed access – As you see, field names are being accessed through strongly typed properties so less runtime and ugly “Object reference not set to an instance…” errors.
public class Product { public Sitecore.Data.Items.Item Item { get; protected set; } public Product(String path) { Item = Sitecore.Context.Database.GetItem(path); } public String Title { get { return Item["Title"]; } } public double Price { get { return Convert.ToDouble(Item["Price"]); } } ... } public class Television : Product { public Television(String path) : base(path) { } public double Size { get { return Convert.ToDouble(Item["Size"]); } } ... }
Isn’t it a waste of time to write similar logic to read items especially if there are hundreds of item types? That is where mapping framework such as Glass.Mapper proves useful. In simple words, it is an ORM for Sitecore items. Your code with glass will look like this:
[SitecoreType(AutoMap=true)] public class Product { public virtual String Title { get; protected set; } public virtual float Price { get; protected set; } public virtual String Description { get; protected set; } } [SitecoreType(AutoMap=true)] public class Television { public virtual String Size{get; protected set}; }
And code behind(.ascx.cs) will change to:
protected void Page_Load(object sender, EventArgs e) { SitecoreContext context = new SitecoreContext(); TV = context.GetItem<Television>("/sitecore/content/home/products/tv/sharp47"); }
Beyond defining business types or concepts by creating classes, you don’t have to write more than single line of imperative code. Additionally these classes are reusable and can be loaded with any other item or even from other data sources such as Salesforce, SAP and databases. It greatly reduces the development and testing effort as data access logic which is a big chunk of any Sitecore implementation is taken care by the framework.
Will write more in coming posts about Glass and other frameworks that promotes extensibility and testability in your code.