Archive for category Team Dev. for Sitecore (TDS)

Customize Glass.Mapper T4 Templates for Sitecore TDS CodeGen

If you are using glass.mapper with TDS and say Sitecore MVC, and have in the past created your models manually, you know that glass codegen is a godsend!

Glass basically provides us with t4 template files and dlls, based on the items included in the TDS project, the code is generated using the t4 templates.

We have used TDS with glass for 3-4 projects now and there were a few customizations that we have had to do in the t4 template files to tailor the code gen files to our needs.

Know your t4 template files:
While enabling glass.mapper to auto generate code for your tds items (models and item properties), you will provide 2 templates

  • Transform File (glassv3header.tt) – for the common header and will appear only once in your generated code file – this includes the namespace using statements / base interface / class for all models.
  • Base Project Transform File (glassv3item.tt) – The other template file will be used in a repetitive manner for every item that code (class / model) is generated for.

2015-09-19_172200

In addition to this, we also use the Code Generation Template (itempaths.tt) file to generate item properties for any items we would want. The properties generated per item, is again decided by the template file itself, but out of the box, contains properties such as the item id, item path, template name and template id.

2015-09-19_172313

Add TemplateId to all codegen classes

One thing we noticed right off the bat, was the lack of a property for the template id in the models! We needed this for many situations, like deciding a separate html rendering based on the template id of the item etc. So we updated the t4 template (glassv3header.tt) to include the template id for every model, including the appropriate sitecore attributes on them to get them to populate as expected. (line below)

Item Name vs a Name field

The header template for the common code for your code gen file, has a property mapped to the item name ‘Name’. We came across a situation where we were working with Sitecore Commerce Connect templates, and the main product template there had a Name field. When we tried generating code for that template, we ran into conflicts! We couldn’t change the name of the field in the Commerce Connect template, so had to update the t4 template (glassv3header.tt) instead to change the ‘Name’ property to ‘ItemName’ (line below)

Error with codegen for System Language template

When we tried adding the sitecore system template ‘/sitecore/templates/System/Language’ into TDS and generating code for it, but we again ran into conflicts here! This is why we again updated the t4 template (glassv3header.tt) to explicitly specify the namespace of the Language property. (line below)

<#@ template language="C#"  #>
<#@ assembly name="System.Core" #>

<#@ include file="Helpers.tt" #>
<#@ include file="StringExtensions.tt" #>
<#@ include file="GeneralExtensions.tt" #>
<#@ include file="Inflector.tt" #>

<#@ import namespace="System" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="HedgehogDevelopment.SitecoreProject.VSIP.CodeGeneration.Models" #>

<#@ parameter name="Model" type="HedgehogDevelopment.SitecoreProject.VSIP.CodeGeneration.Models.ProjectHeader" #>
<#@ parameter name="DefaultNamespace" type="System.String" #>

#pragma warning disable 1591
#pragma warning disable 0108
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by Team Development for Sitecore.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;   
using System.Collections.Generic;   
using System.Linq;
using System.Text;
using Glass.Mapper.Sc.Configuration.Attributes;
using Glass.Mapper.Sc.Configuration;
using Glass.Mapper.Sc.Fields;
using Sitecore.Globalization;
using Sitecore.Data;
using SystemSpecialized = System.Collections.Specialized;


<#
// Calculate the top leve namespace as configured in the target project and
// base namespace as defined in the TDS project
string fullNamespace = JoinNamespaces(DefaultNamespace, Model.BaseNamespace);
#>

namespace <#=fullNamespace #>
{

	public partial interface IGlassBase{
		
		[SitecoreId]
		Guid Id{ get; }

		[SitecoreInfo(SitecoreInfoType.Name)]
		string ItemName { get; }

		[SitecoreInfo(SitecoreInfoType.Language)]
		Sitecore.Globalization.Language Language{ get; }

        [SitecoreInfo(SitecoreInfoType.Version)]
        int Version { get; }

		[SitecoreInfo(SitecoreInfoType.Url)]
		string Url { get; }
	}

	public abstract partial class GlassBase : IGlassBase{
		
		[SitecoreId]
		public virtual Guid Id{ get; private set;}

		[SitecoreInfo(SitecoreInfoType.Name)]
        public string ItemName { get; private set; }

		[SitecoreInfo(SitecoreInfoType.Language)]
		public virtual Sitecore.Globalization.Language Language{ get; private set; }

        [SitecoreInfo(SitecoreInfoType.Version)]
        public virtual int Version { get; private set; }

		[SitecoreInfo(SitecoreInfoType.Url)]
        public virtual string Url { get; private set; }
	}
}

Add a new sitecore field type to enable codegen create the right custom field property types

For various reasons, we have had to add custom fields in Sitecore. For these new fields, by default glassmapper will general Object properties unless we provide a hint to the type of data this new custom field will contain.
For example, the Single Select with SearchSingle Select Tree fields are link fields and contain a single guid, while Multisite Multilist with Search is a list field and contains a list of guids. So we need to map the intended property type in the GetGlassFieldType() method of glassv3item.tt template file:

public static string GetGlassFieldType(SitecoreField field)
{
	if (field != null && field.Type != null)
    {
		// Pull out any 'type' param from the custom data field on the field in TDS
		string customType = GetCustomProperty(field.Data, "type");
		string generic = GetCustomProperty(field.Data, "generic");
		
		if (customType != "")
		{
			if (generic != "")
			{
				return string.Format("{0}<{1}>", customType, generic);
			}
			else
			{
				return customType;
			}
		}

		switch(field.Type.ToLower())
		{
			case "tristate":
				return "TriState";
			case "checkbox":
				return "bool";

			case "date":
			case "datetime":
				return "DateTime";

			case "number":
				return "float";

			case "integer":
				return "int";

			case "treelist with search":
			case "treelist":
			case "treelistex":
			case "treelist descriptive":
			case "checklist":
			case "multilist with search":
			case "multisite multilist with search":
			case "multilist":
	            return string.Format("IEnumerable<{0}>", string.IsNullOrEmpty(generic) ? "Guid" : generic);

			case "grouped droplink":
			case "droplink":
			case "lookup":
			case "droptree":
			case "reference":
			case "tree":
			case "single select with search":
			case "multisite single select with search":
				return "Guid";

			case "file":
				return "File";

			case "image":
				return "Image";

			case "general link":
			case "general link with search":
				return "Link";
			
			case "password":
			case "icon":
			case "rich text":
			case "html":
			case "single-line text":
			case "multi-line text":
			case "frame":
			case "text":
			case "memo":
			case "droplist":
			case "grouped droplist":
			case "valuelookup":
				return "string";
			case "attachment":
			case "word document":
				return "System.IO.Stream";	   
			case "name lookup value list":
			case "name value list":
				return "SystemSpecialized.NameValueCollection";                                                                                                                         
			default:
				return "object /* UNKNOWN */";
		}
	}
	else 
	{
	   throw new Exception("There is no 'Type' field on the " + field.Name + " field.");
	}
}

, , , , , ,

Leave a comment

SUG Bangalore Kick Off!

We had our kick off session of the Sitecore User Group Bangalore yesterday (28 March 2015) and a big thank you to everyone who helped make it a success!

The session started with a brief introduction by David Brown, Engagement Manager at Verndale, followed by an Introductory Session to Sitecore 7.2 with MVC, using TDS and Glassmapper by me.

We had 12 attendees at the session with a couple of attendees joining in remotely.

Following is the recording of the session, and the presentation used.

Unfortunately, we went over the anticipated 2 hours and yet fell short of time to be able to cover glassmapper in detail. So we will organize a glassmapper specific session in an upcoming event!

Looking forward to the next session! Date to be announced soon!

Next SUG

Meanwhile – please do join our group and participate in this poll, to determine the timing of the next session!

Few of pictures from this meetup!

DSCN2934 DSCN2938

15 min break! :)

15 min break! 🙂

, , , , , , , , , , , , , , , , ,

Leave a comment