Fortis vs Glass.Mapper (part 1)

Today, if I start googling on how to map Sitecore temlates to .net classes I will definitely find Glass.Mapper framework at the very top of the search. It has become a standard now – if you are planning a big Sitecore implementation you definitely need to use Glass.Mapper. But is that the best tool for solving these problems?

I have been using Glass on several projects, then I was put in the team which were using Fortis in their implementations and after a few years I am on project which uses Glass again. And to be honest, now I have a feeling that Glass is not perfect at all. And yes, now I am going to hear lots and lots of not very kind words from the whole Glass community. Keep calm guys, lets have some constructive overviews.

This is not going to be a detailed comparison of two frameworks I will just show few cases here.

Will start from the beginning. To me, the best practice on Sitecore project is to keep your sitecore templates versioned and stored in the source control system. You can use TDS, Unicorn, or just serialize your items by yourself using Sitecore serialization API for that. This approach gives you possibility to generate C# classes using your serialized template items. TDS has that feature built in, there are plenty ways of doing it with Unicorn or you can just write your own implementation of template generation from serialized Sitecore items.

Code generation templates

I have been using TDS for both Fortis and Glass.Mapper. Both frameworks provide us with t4 templates for generating classes.

In my solution I have a number of templates with quite simple inheritance. So there is a “Content Page” template which inherits list of data templates.

Glass has generated me next code – interface and class for Content Page template:

[SitecoreType(TemplateId=IContent_PageConstants.TemplateIdString )]
public partial interface IContent_Page : IGlassBase, ISEO, INavigation, ITagging, ISearch, ITitle_Field, IBody_Field, IImage_Field, ISummary_Field
{
}

[SitecoreType(TemplateId=IContent_PageConstants.TemplateIdString)]
public partial class Content_Page : GlassBase, IContent_Page
{

[SitecoreField(IContent_PageConstants.Meta_TitleFieldName)]
public virtual string Meta_Title {get; set;}

[SitecoreField(IContent_PageConstants.Hide_From_MenuFieldName)]
public virtual bool Hide_From_Menu {get; set;}

[SitecoreField(IContent_PageConstants.Navigation_TitleFieldName)]
public virtual string Navigation_Title {get; set;}

[SitecoreField(IContent_PageConstants.TagsFieldName)]
public virtual IEnumerable<Guid> Tags {get; set;}

[SitecoreField(IContent_PageConstants.SearchableFieldName)]
public virtual bool Searchable {get; set;}

[SitecoreField(IContent_PageConstants.Content_TitleFieldName)]
public virtual string Content_Title {get; set;}

[SitecoreField(IContent_PageConstants.Content_BodyFieldName)]
public virtual string Content_Body {get; set;}

[SitecoreField(IContent_PageConstants.Content_ImageFieldName)]
public virtual Image Content_Image {get; set;}

[SitecoreField(IContent_PageConstants.Content_SummaryFieldName)]
public virtual string Content_Summary {get; set;}
}

Looks pretty simple and nice (except naming with ‘_’ symbol :)). Glass says that mapping classes have .net types of properties and that is somehow a good thing, but is it really?

Lets have a look what Fortis T4 template generated:


TemplateMapping("{78356424-60E9-4CA7-9CB2-EEFD842ADAE6}", "InterfaceMap")]
public partial interface IContentPage : ICustomItemWrapper , ISEO, INavigation, ITagging, ISearch, ITitleField, IBodyField, IImageField, ISummaryField
{
}

[PredefinedQuery("TemplateId", ComparisonType.Equal, "{78356424-60E9-4CA7-9CB2-EEFD842ADAE6}", typeof(Guid))]
[TemplateMapping("{78356424-60E9-4CA7-9CB2-EEFD842ADAE6}")]
public partial class ContentPage : CustomItemWrapper, IContentPage
{
private Item _item = null;

public ContentPage(ISpawnProvider spawnProvider) : base(null, spawnProvider) { }

public ContentPage(Guid id, ISpawnProvider spawnProvider) : base(id, spawnProvider) { }

public ContentPage(Guid id, Dictionary&amp;lt;string, object&amp;gt; lazyFields, ISpawnProvider spawnProvider) : base(id, lazyFields, spawnProvider) { }

public ContentPage(Item item, ISpawnProvider spawnProvider) : base(item, spawnProvider)
{
_item = item;
}

[IndexField("meta_title_t")]
public virtual ITextFieldWrapper MetaTitle
{
get { return GetField("Meta Title", "meta_title_t"); }
}

[IndexField("hide_from_menu_b")]
public virtual IBooleanFieldWrapper HideFromMenu
{
get { return GetField("Hide From Menu", "hide_from_menu_b"); }
}

[IndexField("navigation_title_t")]
public virtual ITextFieldWrapper NavigationTitle
{
get { return GetField("Navigation Title", "navigation_title_t"); }
}

[IndexField("tags_sm")]
public virtual IListFieldWrapper Tags
{
get { return GetField("Tags", "tags_sm"); }
}

[IndexField("searchable_b")]
public virtual IBooleanFieldWrapper Searchable
{
get { return GetField("Searchable", "searchable_b"); }
}

[IndexField("content_title_t")]
public virtual ITextFieldWrapper ContentTitle
{
get { return GetField("Content Title", "content_title_t"); }
}

[IndexField("content_body_t")]
public virtual IRichTextFieldWrapper ContentBody
{
get { return GetField("Content Body", "content_body_t"); }
}

public virtual IImageFieldWrapper ContentImage
{
get { return GetField("Content Image"); }
}

[IndexField("content_summary_t")]
public virtual ITextFieldWrapper ContentSummary
{
get { return GetField("Content Summary", "content_summary_t"); }
}

}

We can see the same interface and class, but the implementation looks a bit different. We can see a bit more code in the class and there are search attributes present as well. We will talk about Fortis and ContentSearch later I think. The difference is that Fortis has a field wrapper implementation for each Sitecore field type.

The thing is that to get field value from the typed object Glass has to use reflection every time as it doesn’t know to which field the property is mapped. Fortis generated code includes field name for each field wrapper so that is defined on the compilation time. Basically each property knows to which field it reffers. And that means that Glass works slower here as it needs to spend time for realtime reflection and mappings.

Accessing sitecore items

There is an entry point for both frameworks. In Glass its SitecoreService, in Fortis – ItemFactory.

For example I am implementing a navigation service and want to treat my content pages as INavigation interface which is the base template for my Content Page template. There is code to get item by ID for both frameworks:

Glass:


var navigation = sitecoreService.GetItem<INavigation>(contentPageId);

Fortis:


var navigation = itemFactory.Select<INavigation>(contentPageId);

If I debug my code I will see that in case with Glass the GetItem method returns me an instance of Castle.Proxy.INavigationProxy and it has fields defined in INavigation interface only. Obviously a lot more happening behind the scenes while resolving the item using its interface with Glass – something similar to Database ORMs like Entity Framework, – and that is adding some performance loss for sure. That will work faster if I get my item by its Type definition (not the interface) but why would I do that? I want to work with abstractions in my code everywhere.

In case with Fortis I am getting a plain instance of ContentPage type which is hidden behind the INavigation interface. And I still can cast it to IContentPage and it will work.

Rendering fields

Glass has extremely rich set of extensions for field rendering like @Editable(…) and we can do that in quite a few ways. By some reason we all like extension methods, but isn’t that not very right way of writing code really? There are lots of holy-wars around that but my message is not about it. The thing is when using expressions like these:

@Editable(Model, x => x.Title)
@Editable(x => x.Title)

we are still doing reflection to invoke the lambda expression to find the right property, then Glass needs to do reflection to map the property to the sitecore item field and only then we can call FieldRenderer and render the field. And that extensions may actually require some Glass context in place. I believe that doesn’t work as fast as it may look.

in case with Fortis things are much simpler. Each property is being generated as its own IFieldWrapper as we figured out above. Each FieldWrapper has .Render() method which knows how to render the field. And each property includes the field name so no reflection required and it knows which field to call in sitecore.


@Model.Title.Render()

By the way, each FieldWrapper implements IHtmlString interface which calls the .Render() method inside so in razor views we can just type


@Model.Title

And we still have full support of experience editor as .Render() method uses FieldRenderer object to display the field. And that is much faster.

Performance

Lets play with some measurements. I have created 2 simple solutions. One uses Glass.Mapper, another uses Fortis. I use the same master database on both implementations.

In this test I am going to get the same item 1000 times using Glass and then using Fortis

Glass code:


for (int i = 0; i > count; i++)
{
var navigation = sitecoreService.GetItem(contentPageId);
}

Fortis code:


for (int i = 0; i > count; i++)
{
var navigation = itemFactory.Select(contentPageId);
}

Plain Sitecore Api Code:


for (int i = 0; i > count; i++)
{
var navigation = database.GetItem(new ID(contentPageId));
}

The results are next:

Item Count: 1000

Glass: 39.1 ms

Fortis: 9.5 ms

Sitecore API: 9 ms

Conclusions:

Glass.Mapper is more like an ORM which is too powerful and has quite complex functionality while Fortis is just a wrapper around Sitecore API. Yes, Glass.Mapper is a very good framework and well supported, it has a pretty big community, plenty of tutorials and lots of websites already running it.

This post still isn’t doing a full comparison but it does highlight some performance differences and perhaps I would definitely consider to use Fortis in future projects as I don’t really care about community but I really do about performance and solution architecture.

To be continued…

Advertisements

2 thoughts on “Fortis vs Glass.Mapper (part 1)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s