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

0 comments: