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;

Load BusinessProcessFlow thru JavaScript in Dynamics 365

There is a known defect loading active Business Process Flow on the Form, when you upgrade from CRM 2016 to Dynamics 365. It does not load for some records which came thru ETL. If you check in Advanced Find including Process Id column, Process Id is NULL for these records.

If you want to show BPF for these records which Process id is NULL, you need to call following JS in the form load event.

function setProcessId() {
var processId = Xrm.Page.context.getQueryStringParameters().process;
if (processId == null) {
//Business Process Flow Id
var procesGuid = '03278623-2923-443A-957C-AF56D1B1FC81';, function callbackFunction() { });