Thursday 14 February 2013

Duplicate/Clone an entity in CRM 2011

The ability to clone much of the detail of the current record onto a new instance of that entity is a neat trick that can have lots of very useful applications. A couple of examples could be an opportunity renewal whereby you want to copy most of the original opportunity but maybe want to update a couple of dates to reflect the renewal; or where you want to duplicate a case instead of re-opening an old case, to track time spent more effectively.
There is both a coded and a codeless approach that can be utilised, each of which I will describe below, along with the benefits of each.

Codeless
The premise of the codeless approach is basically to use a self-referencing relationship and relationship mapping. The idea being that you would end up with a list of "child" entities on your parent entity and as child entities are added from the grid the relationship mappings would kick in and populate the data for you on the new child entity. This is the most basic form of cloning – but you can get a working model up and running in minutes. If the user experience is OK to your users then this is the way to go. Configurable and no C#/JavaScript in sight. The downside to this is the aforementioned user experience. Will users want to go to a grid and select "Add New Record"? Probably not. And also do you need some more "run-time" control over what values get set on the new entity? Relationship mapping is great but it is static, "Copy Field A from Parent Entity to Field A of Child Entity" and so on for each property to be mapped. There is no way to say "in a certain circumstance, actually don't just copy the field, but add some new data to it".

A detailed guide to this approach can be found here:
 
http://rc.crm.dynamics.com/RC/2011/en-us/online/5.1_CTP/cloneRecords.aspx
   

Coded
The coded approach offers some more flexibility, and involves adding a "Clone" button to your entity ribbon that calls a JavaScript method on your page. This method is great and a detailed write up is available here:

http://garethtuckercrm.com/2012/07/31/duplicate-record-button-using-jscript-in-microsoft-crm-2011/
   

However, this approach also has its drawbacks. We have now lost our link between the parent and child entities so we have lost that relationship (if we need that relationship of course). And we are now totally coded – there is no configuration available now, the person who wants to amend this function MUST be able to do a little JavaScript. There is also the fact that if you pass too many values to the new form you may end up going too long for a URL (OK you would have to pass a lot of values to get to this, but a few large notes fields would get you well on your way).
My solution to most of the drawbacks of each approach is to combine the two. So we use a self-referencing relationship and relationship mapping as described in the "Codeless" approach, but combine it with a "Clone" entity ribbon button and JavaScript function as described in the "Coded" approach. In order to do this we need to tweak the JavaScript function somewhat. What we are effectively doing is "fooling" CRM into thinking we have actually clicked the "Add New Record" from the related child entity grid ribbon, so we can inherit all of the benefits of the relationship mapping. At the same time we can also override a mapping value by passing the value to the opening form. So when the user clicks the button we can have some logic to say whether we want a particular value overridden, such as a type or a date field.
Here is the JavaScript to pass the parent entity to the new form in order to use field mapping:

       parameters["_CreateFromId"] = Xrm.Page.data.entity.getId();
    parameters["_CreateFromType"] = 3;
    parameters["etc"] = 3;

The _CreateFromId parameter is the ID of the parent record (which is the current record ID). The _CreateFromType is the EntityTypeCode of the current entity. In this case 3 for opportunity. The Entity Type Code list can be found here http://msdn.microsoft.com/en-us/library/bb887791.aspx). Here is a post that describes how to get the Entity Type Code at runtime for a custom entity: http://mileyja.blogspot.co.uk/2011/05/how-to-retrieve-metadata-for-entity.html. The etc parameter is again the Entity Type Code (what the etc stands for). Here it is in the full JavaScript function:

function openChildWindow()
{
    var parameters = {};
    parameters["_CreateFromId"] = Xrm.Page.data.entity.getId();
    parameters["_CreateFromType"] = 3;
    parameters["etc"] = 3;
    Xrm.Utility.openEntityForm("opportunity", null, parameters);
}

As mentioned before, we could override other values that would be handled by the relationship mapping simply by setting them here (as defined in the "Coded" approach above):
 
    parameters["name"] = "NEW NAME";

That would set the "name" property of the new cloned entity to "NEW NAME" regardless of the relationship mapping put in place.

One last thing to mention – you need to place the self-referential lookup on the form somewhere, and hide it.
 
That's about it for this one.
 
The above approaches will achieve cloning of entity level fields only; it will not be able to clone one to many records, such as products on an opportunity. If you need to do this then a plugin would be required to fire on create of the entity. From the plugin you could use the entity populated in the self-referential lookup to obtain all the one to many records and add them into the new entity.
 
Cheers,
Nick

1 comment:

  1. Hi
    i am working with Crm Sdk 2011 and i try to copy each entity alone not all in same file..
    how to do it??
    this is my code in batch file:
    CrmSvcUtil.exe /out:entities /url:http://192.168.137.2/sam/XRMServices/2011/Organization.svc /domain:CRMAmani /username:admin /password:sam /namespace:WebS1 /serviceContextName:XrmServiceContext

    pause

    with this code all the entities are created in same file named entities but i want each entity to be alone

    tnku

    ReplyDelete