Tuesday 21 October 2014

The Sdk.Soap.js – code samples of Sdk.Sync namespace

 

This post is related to my previous post. So, I suggest to read that first using the following link, in case you did not read it yet.

http://ankit.inkeysolutions.com/2014/10/sdksoapjs.html

In this post I’m sharing the sample code for the most common messages of the Sdk.Sync namespace.

Examples:

· Create

function SyncCreateRecord() {
  var contact = new Sdk.Entity("contact");
  var userID = new Sdk.EntityReference("systemuser", "GUID"); //Use the GUID value of user record
  contact.addAttribute(new Sdk.String("lastname", "Sync record Last Name"));
  contact.addAttribute(new Sdk.Lookup("ownerid", userID));
  var createdRecordID = Sdk.Sync.create(contact);
  alert("Contact created successfully : \"" + createdRecordID + "\"");
}

· Update



function SyncUpdateRecord() {
  var contact = new Sdk.Entity("contact");
  contact.addAttribute(new Sdk.Guid("contactid", "GUID")); //Use the GUID value of contact record
  contact.addAttribute(new Sdk.String("lastname", "Sync record Last Name Updated"));
  var result = Sdk.Sync.update(contact);
  if (result == true) {
    alert("Contact updated successfully.");
  }
  else {
    alert("Contact not updated.");
  }
}
· Delete

function SyncDeleteRecord() {
  //Use the GUID value of contact record
  Sdk.Sync.del("contact", "GUID"); 
  alert("Contact deleted successfully.");
}

· Retrieve



function SyncReteriveRecord() {
  var columnSet = new Sdk.ColumnSet();
  columnSet.addColumn("fullname");
  //Use the GUID value of contact record
  var contact = Sdk.Sync.retrieve("contact", "GUID", columnSet);
  alert("Retrieved contact : \"" + contact.getValue("fullname") + "\"");
}

· RetrieveMultiple



o QueryByAttribute



function SyncRetrieveMultipleByQueryByAttribute() {
  var fetchQuery = new Sdk.Query.QueryByAttribute("contact");
  fetchQuery.setColumnSet("fullname");
  fetchQuery.addAttributeValue(new Sdk.String("middlename", "middle"));
  var result = Sdk.Sync.retrieveMultiple(fetchQuery);
  MethodToBePassedTheResults(result);
}


o QueryExpression



function SyncRetrieveMultipleByQueryExpression() {
  var fetchQuery = new Sdk.Query.QueryExpression("contact");
  fetchQuery.addColumn("fullname");
  var middleName = "middle";
  var values = new Sdk.Query.Strings([middleName]);
  fetchQuery.addCondition("contact", "middlename", Sdk.Query.ConditionOperator.Equal, values);
  var result = Sdk.Sync.retrieveMultiple(fetchQuery);
  MethodToBePassedTheResults(result);
}


o FetchExpression



function SyncRetrieveMultipleByFetchXML() {
  var fetchXml = ["<fetch version=\"1.0\" output-format=\"xml-platform\" mapping=\"logical\" distinct=\"false\">",
                    "<entity name=\"contact\"> ",
                    "  <attribute name=\"fullname\" /> ",
                    "  <order attribute=\"fullname\" descending=\"false\" /> ",
                    "  <filter type=\"and\"> ",
                    "    <condition attribute=\"middlename\" operator=\"eq\" value=\"middle\" /> ",
                    "  </filter> ",
                    " </entity> ",
                    " </fetch>"].join("");
  var fetchQuery = new Sdk.Query.FetchExpression(fetchXml);
  var result = Sdk.Sync.retrieveMultiple(fetchQuery);
  MethodToBePassedTheResults(result);


o MethodToBePassedTheResults, a common method which is being used in above RetrieveMultiple options.



function MethodToBePassedTheResults(cb) {
   if (cb.getEntities().getCount() >= 1) {
    alert(cb.getEntities().getCount());
  }
  else {
    alert("No result");
  }
}

· Associate


For this message, I’ve created custom many-to-many relationship between account and contact i.e. new_contact_account.



function SyncAssociateRecord() {
//Use the GUID value of account record
  var account = new Sdk.EntityReference("account", "GUID");
  var collection = new Sdk.Collection(Sdk.EntityReference, new Array(account));
  //Use the GUID value of contact record
  Sdk.Sync.associate("contact", "GUID", "new_contact_account", collection);
  alert("Contact - Account Associated");
 
}

· Disassociate

For this message, I’ve created custom many-to-many relationship between account and contact i.e. new_contact_account.

function SyncDisassociateRecord() {
  //Use the GUID value of account record
  var account = new Sdk.EntityReference("account", "GUID");
  var collection = new Sdk.Collection(Sdk.EntityReference, new Array(account));
  //Use the GUID value of contact record
  Sdk.Sync.disassociate("contact", "GUID", "new_contact_account", collection);
  alert("Contact - Account Disassociated");
 
}

· SetState

This message is not included in common messages file i.e. Sdk.Soap.vsdoc.js. They provided a separate file, the Sdk.SetState.vsdoc.js to incorporate this message. To use this file we need to slightly change the existing code. We need to add the following line as the first line of the Sdk.SetState.vsdoc.js file,

Sdk = window.Sdk || { __namespace: true };

And we need to include two files at entity form load event:

Sdk.Soap.vsdoc.js

Sdk.SetState.vsdoc.js

Now, we are all set to use the following method.



function jQuerySetStateActivateRecord() {
  //Use the GUID value of contact record
  var contactMoniker = new Sdk.EntityReference("contact", "GUID");
  var setStateRequest = new Sdk.SetStateRequest(contactMoniker, 0, 1); 
  //To deactivate record, use same code just pass state = 1 and status = 2) at above line
  Sdk.Sync.execute(setStateRequest);
  alert("Contcat Activated.");
}

I hope this would be helpful. In my upcoming post, I will be covering the sample code for Sdk.JQ and Sdk.Q namespaces.


Thanks for reading this far.

7 comments:

  1. function jQuerySetState(entityName, state, status, desc) {

    try{
    var stateCode = state;
    var statusCode = status;
    var msgDesc = desc;
    var entityId = Xrm.Page.data.entity.getId();
    entityId = entityId.replace('{', '').replace('}', '');

    var entityMoniker = new Sdk.EntityReference(entityName, entityId);

    var setStateRequest = new Sdk.SetStateRequest(entityMoniker, stateCode, statusCode);

    var result = Sdk.Sync.execute(setStateRequest);

    Xrm.Page.data.save().then(successCallback, errorCallback);

    }

    The above is my method. I call this from Ribbon button in CRM 2013. I get an error Sdk.OrganizationRequest Responsetype property must be a Sdk.OrganizationResponse

    ReplyDelete
    Replies
    1. Hi,

      The Sdk.SetState.js file has following two lines at the end of the file.


      Sdk.SetStateRequest.prototype = new Sdk.OrganizationRequest();
      Sdk.SetStateResponse.prototype = new Sdk.OrganizationResponse();

      Please add them in a JavaScript function in that file only and call that function first on entity form load.

      You should not see this error with this change. Let me know if you have any queries.

      Delete
  2. Hi,
    Thank you and this worked for me.

    However, I have registered a plugin on "SetState" Message in PreValidation.
    The plugin tries to check the EntityMoniker and gives an error that "The given key is not present in the dictionary"...

    When I debug, I understand, the InputParametrs does not have EntityType and is null.

    Below is my few lines in plugin:
    IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
    IOrganizationService service = (IOrganizationService)Common.GetCRMService(context, serviceProvider);

    if (context.InputParameters.Contains("EntityMoniker")&&
    context.InputParameters.Contains("State") &&
    ((OptionSetValue)context.InputParameters["State"]).Value == 1 &&
    ((OptionSetValue)context.InputParameters["Status"]).Value == 4)
    {
    ---------------------------------------------------------------------
    So, I tried to set the state of my entiry record using XRMServiceToolKit as below

    var response = XrmServiceToolkit.Soap.SetState(entityname, entityId, stateCode, statusCode);

    This approach also works to set the state of the entity successfully.

    However, the plugin still fails to get EntityMoniker in both the approach.

    Kindly share your views on this issue!

    Thank you.

    ReplyDelete
  3. FYI,

    I am trying to set state to Inactive using Javascript function on ribbon button click.

    But a plugin is registered on PreValidate SetState to do some validation before changing to inactive.

    Only if validation passes, then the record will be inactive.

    ReplyDelete
    Replies
    1. Hi,

      The EntityMoniker is available for "Associate" and "Disassociate" messages and not for "SetState".

      For the "SetState", you should use EntityReference as written in following line for lead entity.

      EntityReference leadId = (EntityReference)iPluginExecutionContext.InputParameters["LeadId"];

      Change the lead to your entity and fetch it's Id and state and status code values from the plugin context.

      I hope this would be helpful.

      Thanks,
      Ankit

      Delete
  4. Hi Ankit,

    Thank you,

    My plugin had other issues and I fixed it. It has nothing to do with Soap.js approach or XRMServiceToolkit.js approach.

    The SetState method explained in your article works great. :-)

    Thanks for this very useful post.

    ReplyDelete