Make Cross Domain Web Service Request through Client Side Scripting in Dynamics CRM

By | October 5, 2015

To perform CRUD operations with CRM data at client side we use ODATA and SOAP services of Microsoft Dynamics CRM. We use XMLHttpRequest to send request to these services to get the response.

Microsoft Dynamics CRM provides below WCF services that we used to manipulate CRM data,

Organization Data Service – Protocol:  OData (REST)

http://<server>/XRMServices/2011/OrganizationData.svc/

Organization Service – Protocol: SOAP

http://<server> /XRMServices/2011/Organization.svc

The request to above WCF services from JavaScript code works because these services are in same domain as the CRM server.

But sometimes we may need to create our own service which accepts data from CRM and sends response back to it at client side and which is hosted on different domain than CRM domain. If we try to call such web service we get an error as No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

This blog will illustrate how to get the response correctly from the WCF service that are hosted on different domain than the domain of MS Dynamics CRM.

For example, at client side using scripting we need to send name of City of account record to WCF service (.svc) (which is hosted on different domain than CRM) to get respective code for that city.

The request to service which is not in same domain as of CRM it’s called Cross Domain access/request.

If we do XMLHttpRequest to different domain than our CRM or Page is on, the browser blocks this request for security reasons.

There are ways to rid of this situation. The JSONP method is use to make cross domain request. We can send CROSS DOMAIN AJAX request using JSONP.

Below is the code snippet that sends cross domain AJAX request,

$.ajax({

url: “http://ad4:51643/WCFService/Services/ProcessData.svc/GetCode”,

dataType: “jsonp”, //set data type as jsonp for cross domain request

contentType: “application/json; charset=utf-8”,

data: “city=Florida”, //pass value for city parameter

success: function (data) {

alert(“Name:” + data);

},

error: function (data) {

if (data.responseText != “done”) {

alert(“ERROR: ” + data.responseText);

}

else {

alert(_msgSendRequest);

}

}

});

Below is the code snippet of WCF service (.svc) function that accept string city and send response in JSON format,

//Data Contract part of WCF service

[DataContract]

public class Company

{

[DataMember]

public string CityCode;

}

//Service Contract and OperationContract part of WCF service

[ServiceContract(Namespace = “JsonpAjaxService”)] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

public class ProcessData

{

// To use HTTP GET, add [WebGet] attribute. (Default ResponseFormat is WebMessageFormat.Json)

// To create an operation that returns XML,

//     add [WebGet(ResponseFormat=WebMessageFormat.Xml)],

//     and include the following line in the operation body:

//         WebOperationContext.Current.OutgoingResponse.ContentType = “text/xml”;

[OperationContract] [WebGet(ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]

 

public void GetCode(string callback, string city)

{

Dictionary<string, string> cityCodes = new Dictionary<string, string>();

cityCodes.Add(“Florida”, “FL”);

cityCodes.Add(“New York”, “NY”);

StringBuilder sb = new StringBuilder();

System.Web.Script.Serialization.JavaScriptSerializer s = new System.Web.Script.Serialization.JavaScriptSerializer();

Company p = new Company() { CityCode = cityCodes[city] };

string json = s.Serialize(p);

sb.Append(callback + “(“);

sb.Append(json);

sb.Append(“);”);

System.Web.HttpContext.Current.Response.Clear();

System.Web.HttpContext.Current.Response.ContentType = “application/json”;

System.Web.HttpContext.Current.Response.Write(sb.ToString());

}

// Add more operations here and mark them with [OperationContract]

}

//web.config file of WCF service

<configuration>

<system.serviceModel>

<behaviors>

<serviceBehaviors>

<behavior name=”ProcessDataAspNetAjaxBehavior” >

<!– Add the following element to your service behavior configuration. –>

<serviceMetadata httpGetEnabled=”true” />

</behavior>

</serviceBehaviors>

<endpointBehaviors>

<behavior name=”ProcessDataAspNetAjaxBehavior”>

<webHttp />

</behavior>

</endpointBehaviors>

</behaviors>

<serviceHostingEnvironment aspNetCompatibilityEnabled=”true”

multipleSiteBindingsEnabled=”true” />

<standardEndpoints>

<webScriptEndpoint>

<standardEndpoint crossDomainScriptAccessEnabled=”true”></standardEndpoint>

</webScriptEndpoint>

</standardEndpoints>

<services>

<service name=”ProcessData” behaviorConfiguration=”ProcessDataAspNetAjaxBehavior”>

<endpoint address=”” behaviorConfiguration=”ProcessDataAspNetAjaxBehavior”

binding=”webHttpBinding” contract=”ProcessData” />

</service>

</services>

</system.serviceModel></configuration>

Important points to make a successful cross domain request,

  • In Ajax request set dataType as “JSONP”
  • Pass required parameter to web service
  • In WCF service (.cs) file add ”ScriptMethod” web attribute as above
  • Along with all required parameter add extra string parameter named as “callback”, in above code the “GetCode” function accepts “callback” and “city” as parameter. We do not need pass value for callback parameter. When our function defined in “OperationContract” has parameter named as “callback” internally JQuery pass value for it.
  • Append the result with callback function and write result in HttpContext.Current.Response. The string that we write to response should be in given format, callback(“{CityCode:”FL”}”);

So this way we can call cross domain request and we get the response in success callback.

Hope this helps!

Make your Dynamics CRM more better with Inogic Add-ons for Dynamics CRM.