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));
            try
            {
                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;
            ms.Close();
            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 + ":" +
                soapClient.ClientCredentials.UserName.Password));
                OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
               //
               //Pass request data
               //
               var serviceResponse = soapClient.ValidateService(requestType);
                return serviceResponse;
            }            
        }
Advertisements

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';
Xrm.Page.data.process.setActiveProcess(procesGuid, function callbackFunction() { });
}
}

How to use Auto Complete in CRM 2016

Introduction

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) {
                ext.getEventSource().showAutoComplete(resultSet);
            } else {
                ext.getEventSource().hideAutoComplete();
            }
        } catch (e) {
            console.log(e);
        }
    };
    Xrm.Page.getControl("address1_stateorprovince").addOnKeyPress(keyPressFcn);
}

New JavaScript Auto Complete Methods

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

showAutoComplete

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.


Xrm.Page.getControl(arg).showAutoComplete(object)

hideAutoComplete

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


Xrm.Page.getControl(arg).hideAutoComplete()

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.

addOnKeyPress

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])
Xrm.Page.getControl("address1_stateorprovince").addOnKeyPress(keyPressFcn);

removeOnKeyPress

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])

fireOnKeyPress

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.

Xrm.Page.getControl(arg).fireOnKeyPress()

Microsoft Dynamics CRM 2015 Update and Microsoft Dynamics Marketing 2015 Update

The next wave of updates for Microsoft Dynamics CRM and Microsoft Dynamics Marketing is expected to arrive before the end of the 2014 calendar year. These updates will add enhancements to sales, marketing, and customer service functionality, and will also add features to facilitate marketing and sales team collaboration.

These are just a few of the highlights of what’s coming:

Microsoft Dynamics CRM

  • Create product families: Boost selling effectiveness with the ability to bundle products and recommend related products for cross-selling/up-selling opportunities.
  • Use sales hierarchies: Manage and report on your sales data in a way that maps to your business. New hierarchical visualizations and roll-ups bring real-time territory and forecasting data to your fingertips.
  • Mobile sales improvements: Increase field sales productivity with flexible, role tailored dashboards and analytics, personalized home pages and the ability to navigate by hierarchy. This version of the tablet app also includes improved support for disconnected scenarios.
  • Access CRM records on the go via voice commands: Cortana is now part of Microsoft Dynamics CRM! For customers with Windows Phone 8.1, you can now use conversational voice commands to seamlessly create follow-up appointments, tasks, and phone calls; quickly find information; view your customer lists; and more. Note: This feature will be available in English only in markets where Cortana is available. Read about Cortana voice commands for CRM in the topic Take a tour of CRM for phones.
  • Enhanced sales processes: Guide sellers toward desired outcomes with enhanced branching logic within your sales processes. Increase impact via automation of business processes and enforcement of business rules across all devices.
  • Expanded case management functionality: Enable agents to provide differentiated levels of support with flexible Service Level Agreements (SLAs). Gain insight into service effectiveness with the ability to track and analyze key metrics like SLAs and thresholds.
  • Microsoft Social Listening availability: Microsoft Dynamics CRM Online customers with a minimum of 10 Professional users automatically have access to Social Listening as part of their subscription at no additional charge. Customers who have an Enterprise subscription also have access to Social Listening but with no minimum user requirement. You can add Microsoft Social Listening subscriptions from the Office 365 Administrative Portal.
  • Microsoft Social Listening for on-premises CRM customers: With this coming release, you can now access Social Listening directly from within Microsoft Dynamics CRM 2015 – even as an on-premises customer – and may also be eligible for a discounted rate. Contact your Microsoft Dynamics partner for more information.
  • Improvements in CRM for Outlook: Set up CRM for Outlook quickly and easily with the completely redesigned Configuration Wizard. With Microsoft Dynamics CRM 2015 for Outlook, users can sync assigned tasks and appointment attachments. Admins can control synchronization between pairs of fields, which provides confidence about where data is coming from and how it’s shared. For more information, see Set up CRM for Outlook.
  • Customizable help: Personalize the user assistance by tailoring the in-product Help content to match the specifics of your Dynamics CRM implementation. You can modify what displays under the Help question-mark icon at either an entity-specific or organization-wide level. Please read Customize the Help experience.

Microsoft Dynamics Marketing

  • Sales and marketing collaboration: Strengthen your marketing and sales synergies with the new Sales Collaboration Panel, which allows sellers to provide input into campaigns and targeting.
  • Manage multi-channel campaigns: Streamline campaign creation and improve segmentation with graphical email editing, A/B and split testing, integrated offers, and approval workflows.
  • Improve B2B marketing: Deepen your lead management capabilities with webinar integration and improved lead scoring, including the ability to introduce multiple lead scoring models.
  • Enhanced marketing resource management: Gain unprecedented visibility into your marketing plan with the new Interactive Marketing Calendar and improve collaborative marketing with Lync click-to-call and webinars.
  • Gain social insights within Microsoft Dynamics Marketing: Display social information collected with Microsoft Social Listening about your brand, campaigns, and more, all within Microsoft Dynamics Marketing.
  • Additional language & geographic availability: Microsoft Dynamics Marketing is now available in Japanese and Russian, bringing the total to 12 languages and 37 countries currently supported. Find more information in the Microsoft Dynamics Marketing Translation Guide.

How to change the DashboardSettings of maximum controls limit in Dynamics CRM2011/2013

The maximum number of controls allowed on CRM2011 or CRM 2013 dashboards is 6. You cannot put the more than 6 graphs/charts/iframes/web resources etc. on the dashboard.

We can extend the number of controls as per the user needs. This setting is applied to the server not a organization setting. So you cannot change this setting for CRM Online but you can change this for an on-premise installation.

Option 1: Using Window Power Shell we can achieve it.

  1. Open the Windows Power Shell command window
  2. Add the Microsoft Dynamics CRM PowerShell snap-in using

Add-PSSnapin Microsoft.Crm.PowerShell
Sometimes You may get the message saying something like “Add-PSSnapin : Cannot add Windows PowerShell snap-in Microsoft.Crm.PowerShell because it is already added.” It is fine no problem.

3.  Run the following 3 commands

$setting = Get-CrmSetting -SettingType DashboardSettings

$setting.MaximumControlsLimit = 10

Set-CrmSetting -Setting $setting

After that open CRM, still you will be see only 6 components on the dashboard design, however you can add extra components based on how much you have set the limit.

Once you crossed the limit you will get following error message.

DashboardSettings

Option 2: If Powershell does not work, use following C# code to do the same

  public static void UpdateDashboardSettings()
        {
            //Create Instance of Deployment Service
            DeploymentServiceClient service = Microsoft.Xrm.Sdk.Deployment.Proxy.ProxyClientHelper.CreateClient(new Uri("http://CRMServer/Organization/XRMDeployment/2011/Deployment.svc"));
            //Use Default network Credentials(User should de Deployment Admin in Deployment Manager and System Admin in CRM)
            service.ClientCredentials.Windows.ClientCredential = (NetworkCredential)CredentialCache.DefaultCredentials;

            //Retrieve Current Dashboard Settings MaximumControlsLimit
            Microsoft.Xrm.Sdk.Deployment.RetrieveRequest retrieveReq = new Microsoft.Xrm.Sdk.Deployment.RetrieveRequest();
            retrieveReq.EntityType = DeploymentEntityType.DashboardSettings;

            Microsoft.Xrm.Sdk.Deployment.RetrieveResponse retrieveRes = (Microsoft.Xrm.Sdk.Deployment.RetrieveResponse)service.Execute(retrieveReq);
            if (retrieveRes != null && retrieveRes.Entity != null)
            {
                DashboardSettings dsCurrentResult = (DashboardSettings)retrieveRes.Entity;
                if (dsCurrentResult != null)
                    Console.WriteLine("Current DashboardSettings MaximumControlsLimit is " + dsCurrentResult.MaximumControlsLimit);
            }
            //Update Current Dashboard Settings MaximumControlsLimit = 10
            Microsoft.Xrm.Sdk.Deployment.UpdateRequest updateReq = new Microsoft.Xrm.Sdk.Deployment.UpdateRequest();
            DashboardSettings ds = new DashboardSettings();
            ds.MaximumControlsLimit = 10;
            updateReq.Entity = ds;
            Microsoft.Xrm.Sdk.Deployment.UpdateResponse updateRes = (Microsoft.Xrm.Sdk.Deployment.UpdateResponse)service.Execute(updateReq);

            //Retrieve again after updating Current Dashboard Settings MaximumControlsLimit
            Microsoft.Xrm.Sdk.Deployment.RetrieveRequest retrieveReq1 = new Microsoft.Xrm.Sdk.Deployment.RetrieveRequest();
            retrieveReq1.EntityType = DeploymentEntityType.DashboardSettings;
            Microsoft.Xrm.Sdk.Deployment.RetrieveResponse retrieveRes1 = (Microsoft.Xrm.Sdk.Deployment.RetrieveResponse)service.Execute(retrieveReq1);

            if (retrieveRes1 != null && retrieveRes1.Entity != null)
            {
                DashboardSettings dsUpdatedResult = (DashboardSettings)retrieveRes1.Entity;
                if (dsUpdatedResult != null)
                    Console.WriteLine("After Updating DashboardSettings MaximumControlsLimit is " + dsUpdatedResult.MaximumControlsLimit);

            }
        }

NOTE: You need add microsoft.xrm.sdk.deployment DLL from SDK to access those Deployment classes and methods. User who is running this should be Deployment Admin in Deployment Manager and Sys Admin in CRM

Incase if you are getting 404 error while accessing Deployment service, you need to check your CRM web server IIS settings and make sure XRMDeployment is not configured in Hidden Segments in IIS, Follow below steps to remove/add XRMDeployment setting in IIS

  1. Open Internet Information Services(IIS) Manager
  2. Expand Server on left navigation
  3. Expand Sites on the Left Navigation
  4. Click on Microsoft Dynamics CRM
  5. Click on “Request Filtering” icon in IIS on right side window
  6. Click on “Hidden Segments” tab on Request Filtering window on right side
  7. If “XRMDeployment” exists then select “XRMDeployment” and right click on “Remove” and say “Yes” to remove “XRMDeployment” from Hidden Segments
  8. Once you are done executing PowerShell, SDK Code you can add using “Add Hidden Segment” option, enter “XRMDeployment” in Hidden Segment window and click on “OK” to close the window.

Build dynamic HTML table and display on entity form using JavaScript and HTML web resource in Dynamics CRM 2011

I have a requirement to build dynamic HTML table and display on Account form using HTML web resource and JavaScript.

Here is my scenario; I have two entities; Account and AccountService. There is 1:N relationship between Account and AccountService. AccountService entity has name and account fields. Requirement is to get account services from AccountService entity based on account guid and display on Account form.

I have created new HTML web resource for displaying account services and added on Account form.

Here is HTML web resource code, I am using oDATA and JavaScript in HTML web resource.

 

<html>
<head>
    <title>Account Services</title>
    <script src="ls_Script_JQuery_1.7.1.min"></script>
    <script src="ClientGlobalContext.js.aspx"></script>
    <script language="javascript" type="text/javascript">
        function loadAccountServices() {
            //Get Account Guid
            var accountId = window.parent.Xrm.Page.data.entity.getId();
            //Get Account Services
            var accountServices = getAccountServices(accountId);
            if (accountServices != null && accountServices.length > 0) {
                var tableData = "";
                for (var i = 0; i < accountServices.length; i++) {
                    var service = accountServices[i].ls_name;
                    if (service != null) {
                        //dynamically add table data with Service Names
                        tableData = tableData + "<tr><td>" + service + "</td></tr>";
                    }
                }
                //Create HTML table
                var table = "<table style='font-family:Segoe UI;font-weight:normal;font-size:13px;'><tr style='height:20px'><td style='text-decoration:underline;'>Account Services</td></tr>" + tableData + "</table>";
                //show table data on the Account form
                window.document.writeln(table);
            }
        }
        //get Account Services
        function getAccountServices(accountId) {
            var serverUrl = location.protocol + "//" + location.host + "/" + Xrm.Page.context.getOrgUniqueName();
            var oDataUri = serverUrl + "/xrmservices/2011/OrganizationData.svc/ls_accountserviceSet?$select=ls_name&$filter=ls_Account/Id eq guid'" + accountId + "'";
            var accountServices = null;
            $.ajax({
                type: "GET",
                contentType: "application/json; charset=utf-8",
                datatype: "json",
                url: oDataUri,
                async: false,
                beforeSend: function (XMLHttpRequest) {
                    XMLHttpRequest.setRequestHeader("Accept", "application/json");
                },
                success: function (data, textStatus, XmlHttpRequest) {
                    if (data != null && data.d.results.length > 0) {
                        accountServices = data.d.results;
                    }
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                }
            });
            return accountServices;
        }
    </script>
</head>
<body onload="loadAccountServices();">
</body>
</html>


How it looks on Account Form:

Account Services

Dynamics CRM 2013 SDK version 6.0.4 available

Microsoft Dynamics CRM 2013 latest SDK Version SDK Version 6.0.2 is now available on MSDN download center.

The following table lists the significant changes made to this version of the SDK.

New and updated topics Description of changes
SDK\Bin Updated the assemblies for Microsoft Dynamics CRM 2013 Update Rollup 2. These assemblies are also compatible with the latest service update for Microsoft Dynamics CRM Online.
SDK\Bin\SolutionPackager.exe Fixed the issue where Solution Packager failed to repack solutions that contain entity level business rules.
Authenticate the user with the web services
Walkthrough: Register a CRM app with Active Directory
Sample: Windows 8 desktop modern SOAP app
Sample: Windows 8 desktop modern OData app
Updated the documentation to include use of Active Directory Federation Services (AD FS) 3.0.
Configure email for incoming messages
SampleCode\CS\BusinessDataModel\
BusinessManagement\ConfigureQueueEmail.cs
SampleCode\VB\BusinessDataModel\
BusinessManagement\ConfigureQueueEmail.vb
Documented deprecated and read-only attribute changes for the email user name and password attributes in the Queue and UserSettings entities.

Changed the sample code, removing the lines of code that set the attributes.

Create a custom workflow activity Removed support for Microsoft .NET Framework 4.5. Added the requirement to digitally sign the assembly.
Install or uninstall the Developer Toolkit Added a statement that the Developer Toolkit can’t be installed into the Express edition of Microsoft Visual Studio.
Xrm.Page.ui (client-side reference) The Xrm.Page.ui.getCurrentControl method is deprecated in Microsoft Dynamics CRM 2013 Update Rollup 2.