{Dynamics CRM + Upsert} Execute Upsert request from client side in Dynamics CRM

Upsert request was introduced in Dynamics CRM 2015 Online Update 1 and on-premise customers got a flavour of it from CRM 2016 onwards. After this feature has been introduced, it has been used so much that writing anything on it is now hackneyed.

However just when you feel you have done it 100 times, you may still find that one scenario suddenly popping up which you might have not implemented in your previous projects and this was exactly one of those. My client wanted to fire an Upsert request from the client side. Basically the requirement was, there was a webresource where the user would fill the necessary information for a record and based on the field values entered, an Upsert request would create/ update the record accordingly.

So what do I need here? Well the first thing I need here is the XML request. And how do I get that?  Did you forget about the wonderful SOAP Logger tool that ships with SDK. Yeah and it still works great. Smile

By any chance you are not aware where you can find the SOAP Logger, you can find in your SDK Download in the following folder structure – SDK\SampleCode\CS\Client\SOAPLogger

Let’s take an example here. For account entity, first I create an alternate key with combination of Account Number + Account Name.

image

I open the SOAP logger and run the below code to get the corresponding XML request for Upsert request

SoapLoggerOrganizationService slos = new SoapLoggerOrganizationService(serverConfig.OrganizationUri, service, output);

                              //Add the code you want to test here:
                              // You must use the SoapLoggerOrganizationService ‘slos’ proxy rather than the IOrganizationService proxy you would normally use.

                              KeyAttributeCollection acckeys = new KeyAttributeCollection();

                              acckeys.Add("accountnumber", "ASH001");
                              acckeys.Add("name", "SOAP Logger for Test");
                              Entity account = new Entity("account", acckeys);
                              account["name"] = "SOAP Logger for Test";

                              UpsertRequest upsert = new UpsertRequest();
                              upsert.Target = account;
                              UpsertResponse response = (UpsertResponse)slos.Execute(upsert);

 

Once I run the above code, the below is the XML Request

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <Execute xmlns="
http://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <request i:type="a:UpsertRequest" xmlns:a="
http://schemas.microsoft.com/xrm/2011/Contracts">
        <a:Parameters xmlns:b="
http://schemas.datacontract.org/2004/07/System.Collections.Generic">
          <a:KeyValuePairOfstringanyType>
            <b:key>Target</b:key>
            <b:value i:type="a:Entity">
              <a:Attributes>
                <a:KeyValuePairOfstringanyType>
                  <b:key>name</b:key>
                  <b:value i:type="c:string" xmlns:c="
http://www.w3.org/2001/XMLSchema">SOAP Logger for Test</b:value>
                </a:KeyValuePairOfstringanyType>
              </a:Attributes>
              <a:EntityState i:nil="true" />
              <a:FormattedValues />
              <a:Id>00000000-0000-0000-0000-000000000000</a:Id>
             <a:KeyAttributes xmlns:c="
http://schemas.microsoft.com/xrm/7.1/Contracts">
                <c:KeyValuePairOfstringanyType>
                  <b:key>accountnumber</b:key>
                  <b:value i:type="d:string" xmlns:d="
http://www.w3.org/2001/XMLSchema">ASH001</b:value>
                </c:KeyValuePairOfstringanyType>
                <c:KeyValuePairOfstringanyType>
                  <b:key>name</b:key>
                  <b:value i:type="d:string" xmlns:d="
http://www.w3.org/2001/XMLSchema">SOAP Logger for Test</b:value>
                </c:KeyValuePairOfstringanyType>
              </a:KeyAttributes>
              <a:LogicalName>account</a:LogicalName>
              <a:RelatedEntities />
              <a:RowVersion i:nil="true" />
            </b:value>
          </a:KeyValuePairOfstringanyType>
        </a:Parameters>
        <a:RequestId i:nil="true" />
        <a:RequestName>Upsert</a:RequestName>
      </request>
    </Execute>
  </s:Body>
</s:Envelope>

This request is just like any other request for Create/ Update except for the highlighted part. If you notice carefully, you could find a new tag in XML request name KeyAttributes. All you need to do is replace the values of the KeyAttributes

Here is the sample code for the same in javascript

var accountNumber = ‘ASH001’;
var accountName = ‘SOAP Logger for Test’;

var request = [‘<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">’,
  ‘<s:Body>’,
    ‘<Execute xmlns="
http://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">’,
      ‘<request i:type="a:UpsertRequest" xmlns:a="
http://schemas.microsoft.com/xrm/2011/Contracts">’,
        ‘<a:Parameters xmlns:b="
http://schemas.datacontract.org/2004/07/System.Collections.Generic">’,
          ‘<a:KeyValuePairOfstringanyType>’,
            ‘<b:key>Target</b:key>’,
            ‘<b:value i:type="a:Entity">’,
              ‘<a:Attributes>’,
                ‘<a:KeyValuePairOfstringanyType>’,
                  ‘<b:key>name</b:key>’,
                  ‘<b:value i:type="c:string" xmlns:c="
http://www.w3.org/2001/XMLSchema">’, accountName, ‘</b:value>’,
                ‘</a:KeyValuePairOfstringanyType>’,
              ‘</a:Attributes>’,
              ‘<a:EntityState i:nil="true" />’,
              ‘<a:FormattedValues />’,
              ‘<a:Id>00000000-0000-0000-0000-000000000000</a:Id>’,
              ‘<a:KeyAttributes xmlns:c="
http://schemas.microsoft.com/xrm/7.1/Contracts">’,
                ‘<c:KeyValuePairOfstringanyType>’,
                  ‘<b:key>accountnumber</b:key>’,
                  ‘<b:value i:type="d:string" xmlns:d="
http://www.w3.org/2001/XMLSchema">’, accountNumber,'</b:value>’,
                ‘</c:KeyValuePairOfstringanyType>’,
             &#
160;  ‘<c:KeyValuePairOfstringanyType>’,
                  ‘<b:key>name</b:key>’,
                  ‘<b:value i:type="d:string" xmlns:d="
http://www.w3.org/2001/XMLSchema">’, accountName, ‘</b:value>’,
                ‘</c:KeyValuePairOfstringanyType>’,
              ‘</a:KeyAttributes>’,
              ‘<a:LogicalName>account</a:LogicalName>’,
              ‘<a:RelatedEntities />’,
              ‘<a:RowVersion i:nil="true" />’,
            ‘</b:value>’,
          ‘</a:KeyValuePairOfstringanyType>’,
        ‘</a:Parameters>’,
        ‘<a:RequestId i:nil="true" />’,
        ‘<a:RequestName>Upsert</a:RequestName>’,
      ‘</request>’,
    ‘</Execute>’,
  ‘</s:Body>’,
‘</s:Envelope>’].join(”);

var req = new XMLHttpRequest();

req.open("POST", Xrm.Page.context.getClientUrl() + "/XRMServices/2011/Organization.svc/web", false);
req.setRequestHeader("Accept", "application/xml, text/xml, */*");
req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
req.setRequestHeader("SOAPAction",
http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute);

req.send(request);

console.log(req.responseText);

 

The below is the response text.

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <ExecuteResponse xmlns="
http://schemas.microsoft.com/xrm/2011/Contracts/Services">
      <ExecuteResult i:type="a:UpsertResponse" xmlns:a="
http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:ResponseName>Upsert</a:ResponseName>
        <a:Results xmlns:b="
http://schemas.datacontract.org/2004/07/System.Collections.Generic">
          <a:KeyValuePairOfstringanyType>
      
     <b:key>RecordCreated</b:key>
            <b:value i:type="c:boolean" xmlns:c="
http://www.w3.org/2001/XMLSchema">false</b:value>
          </a:KeyValuePairOfstringanyType>
          <a:KeyValuePairOfstringanyType>
            <b:key>Target</b:key>
            <b:value i:type="a:EntityReference">
              <a:Id>138f7d7a-1f48-e611-80e9-5065f38be1c1</a:Id>
              <a:KeyAttributes xmlns:c="
http://schemas.microsoft.com/xrm/7.1/Contracts"/>
              <a:LogicalName>account</a:LogicalName>
              <a:Name i:nil="true"/>
              <a:RowVersion i:nil="true"/>
            </b:value>
          </a:KeyValuePairOfstringanyType>
        </a:Results>
      </ExecuteResult>
    </ExecuteResponse>
  </s:Body>
</s:Envelope>

 

In the response, you can find whether the record is created or updated. Please see the highlighted section. I already have an account with same accountnumber and name and hence RecordCreated value has been set to false

 

Hope this helps!