Call External Cross Domain REST API/SOAP Service from CRM Plugins/Custom Workflows.

In Dynamics 365, if you have any requirement to call cross domain REST API/SOAP UI, we can’t directly call from JavaScript, we need to create a custom workflow and create CRM action on top of it. These CRM Actions can be called from anywhere.

For REST API, it is very simple, crate a custom workflow with following code, and call this custom workflow from any CRM Action. This can be used in Plugins also.

 public string CallRESTAPIService(string restAPIURL, string serviceCredentials)
            string jsonResponse = string.Empty;
            var uri = new Uri(restAPIURL);
            var request = WebRequest.Create(uri);
            request.Method = WebRequestMethods.Http.Get;
            request.ContentType = "application/json";
            request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(serviceCredentials));
                using (var response = request.GetResponse())
                    using (var reader = new StreamReader(response.GetResponseStream()))
                        jsonResponse = reader.ReadToEnd();
            catch (System.Exception ex)
                throw ex;
            return jsonResponse;

For SOAP Service, if you have requirement to call within plugin it is simple. If you want to call from JavaScript, you have to convert request and response into JSON format. First you have to convert JSON Request into C# Object and then C# Object Response to JSON Response. There are two options;
• Newtonsoft.Json Nuget library. If you are using, you need to always merge your custom workflow/plugin DLL
• DataContractJsonSerializer- System.Runtime.Serialization assembly should be added to use this. No need to merge the DLL.

 public SOAPServiceRequest DeSerializeJSONRequestToObject(string requestJSON)
            SOAPServiceRequest deserializedRequest = new SOAPServiceRequest();
            MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(requestJSON));
            DataContractJsonSerializer ser = new DataContractJsonSerializer(deserializedRequest.GetType());
            deserializedRequest = ser.ReadObject(ms) as SOAPServiceRequest;
            return deserializedRequest;

        public string SerializeResponseObjectToJSON(SOAPServiceResponse reponse)
            string strJSON = string.Empty;
            using (MemoryStream SerializememoryStream = new MemoryStream())
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(SOAPServiceResponse));
                serializer.WriteObject(SerializememoryStream, reponse);
                SerializememoryStream.Position = 0;
                StreamReader sr = new StreamReader(SerializememoryStream);
                strJSON = sr.ReadToEnd();
            return strJSON;

        public SOAPServiceResponse CallAddressValidation(ITracingService tracingService, string serviceURL, string serviceUserName, string servicePassword, string crmUserName, string addressLine, string city, string state, string postalCode)
            BasicHttpsBinding binding = new BasicHttpsBinding();
            EndpointAddress address = new EndpointAddress(serviceURL);
            ServiceSoapClient soapClient = new ServiceSoapClient(binding, address);
            soapClient.ClientCredentials.UserName.UserName = serviceUserName;
            soapClient.ClientCredentials.UserName.Password = servicePassword;
            SOAPServiceRequest requestType = new SOAPServiceRequest();    
            using (OperationContextScope scope = new OperationContextScope(soapClient.InnerChannel))
                HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
                httpRequestProperty.Headers[HttpRequestHeader.Authorization] = "Basic " +
                Convert.ToBase64String(Encoding.ASCII.GetBytes(soapClient.ClientCredentials.UserName.UserName + ":" +
                OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
               //Pass request data
               var serviceResponse = soapClient.ValidateService(requestType);
                return serviceResponse;

How to use Auto Complete in CRM 2016


Dynamics CRM 2016 comes with new scripting features for Auto Complete, which allows to configure auto complete feature for single line text fields.
We can now use JavaScript code to configure the auto-completion experience in CRM by using the following client-side APIs introduced in Microsoft Dynamics CRM Online 2016 Update and Microsoft Dynamics CRM 2016 (on-premises): getValueKeypress methods, and Auto-completion methods.

How to Configure Auto Complete

Let us take an example to provide an auto complete list of States for the State field on Contact form.

To enable Auto complete functionality work on Contact form State field, we need to call the function on the contact form load as shown below. In this example, we have called “suggestListOfStates” function on form load as shown below.

function suggestListOfStates() {
    states = [
           { state: 'Andaman and Nicobar Islands', capital: 'Port Blair', code: '1' },
           { state: 'Andhra Pradesh', capital: 'Vijayawada', code: '2' },
           { state: 'Arunachal Pradesh', capital: 'Itanagar', code: '3' },
           { state: 'Assam', capital: 'Dispur', code: '4' },
           { state: 'Bihar', capital: 'Patna', code: '5' },
           { state: 'Chandigarh', capital: 'Chandigarh', code: '6' },
           { state: 'Chhattisgarh', capital: 'Raipur', code: '7' },
           { state: 'Dadra and Nagar Haveli', capital: 'Silvassa', code: '8' },
           { state: 'Daman and Diu', capital: 'Daman', code: '9' },
           { state: 'National Capital Territory of Delhi', capital: 'Delhi', code: '10' },
           { state: 'Goa', capital: 'Panaji', code: '11' },
           { state: 'Gujarat', capital: 'Gandhinagar', code: '12' },
           { state: 'Haryana', capital: 'Chandigarh', code: '13' },
           { state: 'Himachal Pradesh', capital: 'Shimla', code: '14' },
           { state: 'Jammu and Kashmir', capital: 'Srinagar (S) and Jammu(W)', code: '15' },
           { state: 'Jharkhand', capital: 'Ranchi', code: '16' },
           { state: 'Karnataka', capital: 'Bengaluru', code: '17' },
           { state: 'Kerala', capital: 'Thiruvananthapuram', code: '18' },
           { state: 'Lakshadweep', capital: 'Kavaratti', code: '19' },
           { state: 'Madhya Pradesh', capital: 'Bhopal', code: '20' },
           { state: 'Maharashtra', capital: 'Mumbai', code: '21' },
           { state: 'Manipur', capital: 'Imphal', code: '22' },
           { state: 'Meghalaya', capital: 'Shillong', code: '23' },
           { state: 'Mizoram', capital: 'Aizawl', code: '24' },
           { state: 'Nagaland', capital: 'Kohima', code: '25' },
           { state: 'Orissa', capital: 'Bhubaneswar', code: '26' },
           { state: 'Pondicherry', capital: 'Pondicherry', code: '27' },
           { state: 'Punjab', capital: 'Chandigarh', code: '28' },
           { state: 'Rajasthan', capital: 'Jaipur', code: '29' },
           { state: 'Sikkim', capital: 'Gangtok', code: '30' },
           { state: 'Tamil Nadu', capital: 'Chennai', code: '31' },
           { state: 'Telangana', capital: 'Hyderabad', code: '32' },
           { state: 'Tripura', capital: 'Agartala', code: '33' },
           { state: 'Uttar Pradesh', capital: 'Lucknow', code: '34' },
           { state: 'West Bengal', capital: 'Kolkata', code: '35' }
    var keyPressFcn = function (ext) {

        try {
            var userInput = Xrm.Page.getControl("address1_stateorprovince").getValue();
            resultSet = {
                results: new Array(),
            var userInputLowerCase = userInput.toLowerCase();
            for (i = 0; i < states.length; i++) {                 if (userInputLowerCase === states[i].state.substring(0, userInputLowerCase.length).toLowerCase()) {                     resultSet.results.push({                         id: i,                         fields: [states[i].state, states[i].capital ]                     });                 }                 if (resultSet.results.length >= 10) break;
            if (resultSet.results.length > 0) {
            } else {
        } catch (e) {

New JavaScript Auto Complete Methods

Use the showAutoComplete and hideAutoComplete methods to configure the auto-completion experience in text controls in forms.


Use this to show up to 10 matching strings in a drop-down list as users press keys to type character in a specific text field. You can also add a custom command with an icon at the bottom of the drop-down list. On selecting an item in the drop-down list, the value in the text field changes to the selected item, the drop-down list disappears, and the OnChange event for the text field is invoked.



Use this function to hide the auto-completion drop-down list you configured for a specific text field.


We don’t have to explicitly use the hideAutoComplete method because, by default, the drop-down list hides automatically if the user clicks elsewhere or if a new drop-down list is displayed. This function is available in case developers need to explicitly hide the auto-completion drop-down list to handle a custom scenario.

New JavaScript Keypress Methods

Use addOnKeyPress, removeOnKeyPress, and fireOnKeyPress methods to provide immediate feedback or take actions as user types in a control. These methods enable you to perform data validations in a control even before the user commits (saves) the value in a form.


Use this to add a function as an event handler for the keypress event so that the function is called when you type a character in the specific text or number field.

Xrm.Page.getControl(arg).addOnKeyPress([function reference])


Use this to remove an event handler for a text or number field that you added using addOnKeyPress.

Xrm.Page.getControl(arg).removeOnKeyPress([function reference])


Use this to manually fire an event handler that you created for a specific text or number field to be executed on the keypress event.