One of my customers wanted to create Quote templates we had to figure out how it should be done – we thought about using opportunities as templates when choosing an opportunity as leading opp it is possible to copy products through. But i think that is a very limited solution. So we decided to make it possible to mark Quotes as Templates and then it is possible to clone them – but cloning isn’t supported out of the box so after spending an evening trying different solutions i finally found a method that i believe will work. A generic method that works with the dynamic entity.
1: public static DynamicEntity clone(this DynamicEntity entity)
2: {
3: DynamicEntity newClone = new DynamicEntity(entity.Name);
4: CrmService svc = CrmServiceManager.GetCrmService();
5: MetadataService meta = CrmServiceManager.GetMetadataService();
6: RetrieveEntityRequest reReq = new RetrieveEntityRequest();
7: reReq.EntityItems = EntityItems.All;
8: reReq.LogicalName = entity.Name;
9:
10: RetrieveEntityResponse reRes = meta.Execute(reReq) as RetrieveEntityResponse;
11: EntityMetadata entityData =reRes.EntityMetadata;
12:
13: for (int y = 0; y < entityData.Attributes.Length; y++)
14: {
15: if (entityData.Attributes[y].LogicalName != null)
16: {
17: if (entityData.Attributes[y].ValidForCreate.Value)
18: {
19: CrmAttributeType aType = entityData.Attributes[y].AttributeType;
20:
21: if (aType.Value.Equals(AttributeType.Boolean))
22: cloneBooleanAttribute(entity, newClone, entityData.Attributes[y].LogicalName);
23: else if (aType.Value.Equals(AttributeType.DateTime))
24: cloneDateTimeAttribute(entity, newClone, entityData.Attributes[y].LogicalName);
25: else if (aType.Value.Equals(AttributeType.Decimal))
26: cloneDecimalAttribute(entity, newClone, entityData.Attributes[y].LogicalName);
27: else if (aType.Value.Equals(AttributeType.Float))
28: cloneBooleanAttribute(entity, newClone, entityData.Attributes[y].LogicalName);
29: else if (aType.Value.Equals(AttributeType.Integer))
30: cloneNumberAttribute(entity, newClone, entityData.Attributes[y].LogicalName);
31: else if (aType.Value.Equals(AttributeType.Lookup))
32: cloneLookupAttribute(entity, newClone, entityData.Attributes[y].LogicalName);
33: else if (aType.Value.Equals(AttributeType.Memo))
34: cloneBooleanAttribute(entity, newClone, entityData.Attributes[y].LogicalName);
35: else if (aType.Value.Equals(AttributeType.Money))
36: cloneMoneyAttribute(entity, newClone, entityData.Attributes[y].LogicalName);
37: else if (aType.Value.Equals(AttributeType.Picklist))
38: clonePicklistAttribute(entity, newClone, entityData.Attributes[y].LogicalName);
39: else if (aType.Value.Equals(AttributeType.String))
40: cloneStringAttribute(entity, newClone, entityData.Attributes[y].LogicalName);
41: }
42: }
43: }
44: return newClone;
45: }
46: }
47: }
the clone[crmdatatype]Attribute just clones the value of that specific type.
1: private static void cloneDecimalAttribute(DynamicEntity masterEntity, DynamicEntity subEntity, string attributeName)
2: {
3: if (masterEntity.GetCrmDecimal(attributeName) != null)
4: subEntity.Properties.Add(new CrmDecimalProperty(attributeName, masterEntity.GetCrmDecimal(attributeName)));
5: }
I hope you find this usefull.
Take care.
