Thursday, 3 April 2008

Email Templates with Custom Entities

I've recently been doing some development work creating emails based on templates. In most cases this is straightforward, once you've applied CRM 3.0 Update Rollup 1, 2 or 3, and also updated any web references. However, there are a couple of quirks I found when trying to use custom entities.

First; you can only use Global templates with custom entities. CRM 3.0 does not allow you to create an entity-specific template. This led to the first quirk; I was using a QueryExpression to find a specific template by name, and also templatetypecode (as CRM allows you to create templates with the same name but on different entities). When searching for a Global template, the templatetypecode is systemuser, rather than null as I was expecting.

Next, when using InstantiateTemplateRequest, it failed if the ObjectType were set to any custom entity. The error message is the unhelpful 'An unexpected error occurred'. Again, the solution is to treat a Global template as if it were actually a template for the systemuser entity. Therefore to make it work you have to specify an ObjectId and ObjectType for a systemuser - it doesn't seem to matter which systemuserid you use.

Putting this together, the following code shows how to create an email based on a template for a custom entity:

public email CreateEmailFromGlobalTemplate(string TemplateName, string EntityTypeName, Guid ObjectId, Guid SomeUserId)
QueryByAttribute qa = new QueryByAttribute();
qa.EntityName = EntityName.template.ToString();
qa.Attributes = new string[] {"title", "templatetypecode"};
qa.Values = new object[] {TemplateName, EntityName.systemuser.ToString()}; // Use systemuser for global template
ColumnSet cs = new ColumnSet();
cs.Attributes = new string[]{"templateid"};
qa.ColumnSet = cs;
BusinessEntityCollection bec = svc.RetrieveMultiple(qa);
if (bec == null && bec.BusinessEntities.Length == 0)
throw new Exception("Cannot find template");
Guid templateId = ((template) bec.BusinessEntities[0]).templateid.Value;
InstantiateTemplateRequest req = new InstantiateTemplateRequest();
req.ObjectId = SomeUserId; // Any valid systemuserid
req.ObjectType = EntityName.systemuser.ToString(); // Use systemuser for global template
req.TemplateId = templateId;
InstantiateTemplateResponse resp = (InstantiateTemplateResponse) svc.Execute(req);
if (resp == null && resp.BusinessEntityCollection.BusinessEntities.Length == 0)
throw new Exception("Cannot create email");
email newMail = (email) resp.BusinessEntityCollection.BusinessEntities[0];
newMail.regardingobjectid = new Lookup();
newMail.regardingobjectid.type = EntityTypeName;
newMail.regardingobjectid.Value = ObjectId;
return newMail;

One more thing to bear in mind: If you use InstantiateTemplateRequest then the code has to run under a CRM context of a live user, rather than the SYSTEM user, otherwise you will get the error 'The specified users settings have not yet been created' - I guess because CRM also looks at user templates


Prologic Corporation said...

This is a good article & good site.Thank you for sharing this article. It is help us following categorize:
healthcare, e commerce, programming, multi platform,inventory management, cloud-based solutions, it consulting, retail, manufacturing, CRM, technology means, digital supply chain management, Delivering high-quality service for your business applications,
Solutions for all Industries,
Getting your applications talking is the key to better business processes,
Rapid web services solutions for real business problems,
Web-based Corporate Document Management System,
Outsourcing Solution,
Financial and Operations Business Intelligence Solution,

Our address:
2002 Timberloch Place, Suite 200
The Woodlands, TX 77380