Showing posts with label SOAP. Show all posts
Showing posts with label SOAP. Show all posts

Tuesday, August 19, 2014

How to manage ODATA 50 records limitation

Hi Guys,

When we use javascript in Dynamics CRM webresources we often ask this question : Did I use SOAP or ODATA ?
For those who have chosen ODATA, when they need to retrieve many recods they are quickly confronted with a classic problem . This problem is : Your resultset contains only 50 records and if you need to get the 200 accounts that you need you should use pagination.

There are three ways to manage this limitation:
- First One: is to accept it and to use pagination to get your data.
In this case, here is the way to use pagination in ODATA queries.

You can create an array to get all records like this array : relatedAccounts[] and a javascript function called GetRecords(url) with a parameter containning the url of your ODATA Request.

The callback success  of the ajax method of jQuery library retrieve the first page of the resultset.

But if you __next member of the data.d object you will got the url of the next page of your resultset.

So, Now you should call the same method GetRecords by passing the new url. Look at this javascript source code :

  1. relatedAccounts = [];
  2.  
  3. function GetAllAccountsRecords() {
  4.     var serverUrl = Xrm.Page.context.getServerUrl();
  5.     var oDataUri = serverUrl + "/xrmservices/2011/OrganizationData.svc/AccountSet?$select=AccountId,Name,&$filter=StateCode/Value eq 0";
  6.     GetRecords(oDataUri);
  7.     var totalRecords = relatedAccounts.length;
  8. }
  9.  
  10. function GetRecords(url) {
  11.     jQuery.ajax({
  12.         type: "GET",
  13.         contentType: "application/json; charset=utf-8",
  14.         datatype: "json",
  15.         url: url,
  16.         async: false,
  17.         beforeSend: function (XMLHttpRequest) {
  18.             XMLHttpRequest.setRequestHeader("Accept", "application/json");
  19.         },
  20.         success: function (data, textStatus, XmlHttpRequest) {
  21.             if (data && data.d != null && data.d.results != null) {
  22.                 AddRecordsToArray(data.d.results);
  23.                 FetchRecordsCallBack(data.d);
  24.             }
  25.         },
  26.         error: function (XmlHttpRequest, textStatus, errorThrown) {
  27.             alert("Error :  has occured during retrieval of the records ");
  28.         }
  29.     });
  30. }
  31.  
  32. function AddRecordsToArray(records) {
  33.     for (var i = 0; i < records.length; i++) {
  34.         relatedAccounts.push(records[i]);
  35.     }
  36. }
  37.  
  38. function FetchRecordsCallBack(records) {
  39.     if (records.__next != null) {
  40.         var url = records.__next;
  41.         GetRecords(url);
  42.     }
  43. }

That means that you use a reccursive method. This method will stop executing when the data.d.__next = null.

When this method stops, you will got all your records in the relatedAccounts array.

- Second One: is to say no I should increase this limitation.
In this case, It's possible but if you increase this limitation to 250 you can got a retrieve that returns 300 records for example and you will be in the same case of 50 records.
But if you say no matter I need to increase it to 250 you have to modify MaxResultsPerCollection property in ServerSettings configuration table in MSCRM_Config database.

You should know that this modification of server settings impact all the server CRM organizations.

Now you can do it using Deployment Service like this :


Or you can do it also by PowerShell cmdlets like this :

  1. Add-PSSnapin Microsoft.Crm.PowerShell
  2. $setting = New-Object "Microsoft.Xrm.Sdk.Deployment.ConfigurationEntity"
  3. $setting.LogicalName = "ServerSettings"
  4. $setting.Attributes = New-Object "Microsoft.Xrm.Sdk.Deployment.AttributeCollection"
  5. $attribute = New-Object "System.Collections.Generic.KeyValuePair[String, Object]" ("MaxResultsPerCollection", 250)
  6. $setting.Attributes.Add($attribute)
  7. Set-CrmAdvancedSetting -Entity $setting

After executing this cmdlets run IISRESET ou restart IIS service because these kind of settings are cached.

By the way ServerSettings table contains many other settings that you can show in this link : http://msdn.microsoft.com/en-us/library/gg334675.aspx


- Third One: is to get only 50 records and you show a message to say: This resultset is capped with 50 records you should use more filters to refine search.
That's all :)

Thursday, April 3, 2014

How to Close Incident using SOAP on CRM 2011

Hi Guys,

The IncidentResolution entity is a particular entity that we can not modify or form neither fields.

So when you need to put an automatic value in Resolution field (subject) you cannot customize form by adding jscript code.

The only way to do it, is by hiding the Resolve Case button:on Incident form/home page Ribbon, and to create your own custom resolution window or dialog and should send a SOAP request to the CRM Server to close the incident.

There is the most complete source code that you allow to close your incident by sending : Subject, TimeSpent and Description data. This code is synchronous.

Source Code
  1. if (typeof (Sdk) == "undefined")
  2. { Sdk = { __namespace: true }; }
  3. //This will establish a more unique namespace for functions in this library. This will reduce the
  4. // potential for functions to be overwritten due to a duplicate name when the library is loaded.
  5. Sdk.Tools = {
  6.     _getServerUrl: function () {
  7.         ///<summary>
  8.         /// Returns the URL for the SOAP endpoint using the context information available in the form
  9.         /// or HTML Web resource.
  10.         ///</summary>
  11.         var OrgServicePath = "/XRMServices/2011/Organization.svc/web";
  12.         var serverUrl = "";
  13.         if (typeof GetGlobalContext == "function") {
  14.             var context = GetGlobalContext();
  15.             serverUrl = context.getServerUrl();
  16.         }
  17.         else {
  18.             if (typeof Xrm.Page.context == "object") {
  19.                 serverUrl = Xrm.Page.context.getServerUrl();
  20.             }
  21.             else { throw new Error("Unable to access the server URL"); }
  22.         }
  23.         if (serverUrl.match(/\/$/)) {
  24.             serverUrl = serverUrl.substring(0, serverUrl.length - 1);
  25.         }
  26.         return serverUrl + OrgServicePath;
  27.     },
  28.     CloseIncidentRequest: function (incidentId, subject, resolutionTypeValue, durationValue, description) {
  29.  
  30.         var requestMain = ""
  31.         requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
  32.         requestMain += "  <s:Body>";
  33.         requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
  34.         requestMain += "      <request i:type=\"b:CloseIncidentRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
  35.         requestMain += "        <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
  36.         requestMain += "          <a:KeyValuePairOfstringanyType>";
  37.         requestMain += "            <c:key>IncidentResolution</c:key>";
  38.         requestMain += "            <c:value i:type=\"a:Entity\">";
  39.         requestMain += "              <a:Attributes>";
  40.         requestMain += "                <a:KeyValuePairOfstringanyType>";
  41.         requestMain += "                  <c:key>incidentid</c:key>";
  42.         requestMain += "                  <c:value i:type=\"a:EntityReference\">";
  43.         requestMain += "                    <a:Id>" + incidentId + "</a:Id>";
  44.         requestMain += "                    <a:LogicalName>incident</a:LogicalName>";
  45.         requestMain += "                    <a:Name i:nil=\"true\" />";
  46.         requestMain += "                  </c:value>";
  47.         requestMain += "                </a:KeyValuePairOfstringanyType>";
  48.         requestMain += "                <a:KeyValuePairOfstringanyType>";
  49.         requestMain += "                  <c:key>subject</c:key>";
  50.         requestMain += "                  <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">" + subject + "</c:value>";
  51.         requestMain += "                </a:KeyValuePairOfstringanyType>";
  52.         requestMain += "                <a:KeyValuePairOfstringanyType>";
  53.         requestMain += "                  <c:key>description</c:key>";
  54.         requestMain += "                  <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">" + description + "</c:value>";
  55.         requestMain += "                </a:KeyValuePairOfstringanyType>";
  56.         requestMain += "                <a:KeyValuePairOfstringanyType>";
  57.         requestMain += "                  <c:key>timespent</c:key>";
  58.         requestMain += "                  <c:value i:type=\"d:int\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">" + durationValue + "</c:value>";
  59.         requestMain += "                </a:KeyValuePairOfstringanyType>";
  60.         requestMain += "              </a:Attributes>";
  61.         requestMain += "              <a:EntityState i:nil=\"true\" />";
  62.         requestMain += "              <a:FormattedValues />";
  63.         requestMain += "              <a:Id>00000000-0000-0000-0000-000000000000</a:Id>";
  64.         requestMain += "              <a:LogicalName>incidentresolution</a:LogicalName>";
  65.         requestMain += "              <a:RelatedEntities />";
  66.         requestMain += "            </c:value>";
  67.         requestMain += "          </a:KeyValuePairOfstringanyType>";
  68.         requestMain += "          <a:KeyValuePairOfstringanyType>";
  69.         requestMain += "            <c:key>Status</c:key>";
  70.         requestMain += "            <c:value i:type=\"a:OptionSetValue\">";
  71.         requestMain += "              <a:Value>" + resolutionTypeValue + "</a:Value>";
  72.         requestMain += "            </c:value>";
  73.         requestMain += "          </a:KeyValuePairOfstringanyType>";
  74.         requestMain += "        </a:Parameters>";
  75.         requestMain += "        <a:RequestId i:nil=\"true\" />";
  76.         requestMain += "        <a:RequestName>CloseIncident</a:RequestName>";
  77.         requestMain += "      </request>";
  78.         requestMain += "    </Execute>";
  79.         requestMain += "  </s:Body>";
  80.         requestMain += "</s:Envelope>";
  81.         var req = new XMLHttpRequest();
  82.         req.open("POST", Sdk.Tools._getServerUrl(), false)
  83.         // Responses will return XML. It isn't possible to return JSON.
  84.         req.setRequestHeader("Accept", "application/xml, text/xml, */*");
  85.         req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
  86.         req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
  87.         req.send(requestMain);
  88.  
  89.         //work with response here
  90.         return req.responseXML.xml;
  91.     },
  92.     __namespace: true
  93. };

Enjoy yourself,

N.JL