Channel integration in Unified Service Desk


Channel Integration Framework (CIF) is an extensible framework to integrate third-party channel providers with D365 Unified Interface Apps using a browser-based JavaScript API library. Read more about Dynamics 365 Channel Integration Framework.

If you have already developed a cloud-based channel using the Channel Integration Framework APIs, then in this blog I will explain how you can leverage Channel Integration Framework (Hosted Control) and Unified Service Desk capabilities to host the same channel inside Unified Service Desk.

In this blog, I'm considering that your channel is a softphone.

Pre-requisites

To use Channel Integration Framework (Hosted Control), you need Unified Service Desk latest client and solutions (version >= 4.1).

Read the blog on how to get the access to Unified Service Desk 4.1 (Preview).

1. Create a Channel Integration Framework hosted control

Please read on how to Create a Channel Integration Framework hosted control inside Unified Service Desk for your softphone.

In CIF, for each channel provider you can create a new Channel Provider record using the Channel Integration Framework app.

Similarly in Unified Service Desk, you can create a new hosted control for each provider, by giving their corresponding Channel URL. As most of the softphone implementations use modern APIs, which may not be supported in IE Process or Internal WPF, so please use latest Chrome Process or Edge Process as hosting type inside Unified Service Desk.

2. Launch the control

After the hosted control is created, to launch the control you can fire default action on this control wherever you want to launch it. This will navigate to the corresponding channel URL inside this control. (ex : you can have it on NewSession event on CRM Global Manager).

3. Configure Actions calls

When we load this CIF Softphone on web, it is loaded in the right panel in Unified Interface and all the APIs called from here are executed in the context of the Unified Interface page available on the left hand side. For those who know about Unified Service Desk might be aware that all the pages in Unified Service Desk are decoupled and they don’t have direct connection between them. So how do we handle these APIs inside Unified Service Desk?

Each call made to the CIF API using Microsoft.CIFramework gets translated to a corresponding event on this hosted control. To know about all the events and their data structure, see Channel Integration Framework (Hosted Control).

On all the events, you will need to configure action calls inside Unified Service Desk to do  the required things.

Below are few mentioned things that you can do :

For most of the APIs you can use RunXrmCommand on Unified Interface Page control and pass the data given by these events.

For each CIF API you can use success callback and error callback functions as all of them return a promise, on web resolving or rejecting the promise was taken care by CIF library. But inside Unified Service Desk it is your responsibility to implement CIF (Unified Service Desk configuration) to resolve or reject the promise using “UpdateCifContext” action call exposed by CIF Hosted control.

CIF Hosted Control Events:

  1. RetrieveRecord :
    1. The parameters passed in the event are
      1. entityName
      2. entityId
      3. queryParameters
    2. You can use api mentioned RetrieveRecord (CIF JavaScript API).
    3. Now if you want to pass the details of the retrieved record back to the CIF control, you can use the action call “UpdateCifContext” exposed by CIF Hosted control.
    4. A sample RunXrmCommand function implementation is given below: Example :
      function retrieveRecord(context, CifHostedControl, corrId, entityName, entityId, queryParameters){
      Xrm.WebApi.retrieveRecord(entityName, entityId, queryParameters).then(
      function(res){
      var data = "corrId='"+ corrId + "' %0D%0A";
      data += "action='resolve' " + "%0D%0A";
      data += "result=" + JSON.stringify(res) + "%0D%0A";
      window.top.notifyUSD("http://uii/"+CifHostedControl+"/UpdateCifContext?"+ data);
      },
      
      function(err){
      var data = "corrId='"+ corrId + "' %0D%0A";
      data += "action='reject' " + "%0D%0A";
      data += "result=" + JSON.stringify(err) + "%0D%0A";
      window.top.notifyUSD("http://uii/"+CifHostedControl+"/UpdateCifContext?"+ data);
      }
      );
      }

      In the above function, CIF Hosted Control is the name of the Hosted Control that the event was fired from, corrId is the correlation ID that was passed in the data of the Unified Service Desk event, and other parameters are also from the data from the Unified Service Desk event.

      The data in the above function call should be in the format (Third line has the name of the hosted control on my org):

      webResourceName=msdyusd_CIFXRMCommandsResource
      functionName=retrieveRecord
      'CIF Chat Control'
      '[[corrId]+]'
      '[[entity]+]'
      '[[entityId]+]'
      '[[queryParameters]+]'

      This way the data can be passed back to the calling API function. (This sample snippet can be modified to suit other APIs as well. Not repeating the same for the below APIs)

  2. CreateRecord : Api reference
  3. DeleteRecord : Api reference
  4. UpdateRecord : Api reference
  5. GetEntityMetadata : Api reference
  6. OpenForm : Api reference
  7. RenderSearchPage :
    1. The data of this event is of the format :
      "entity"="contact"
      "searchString"="cont"
      "corrId"="svwbr"
      
    2. You can navigate to multi-entity search page inside USD using navigate action call with URL like : url = /main.aspx?pagetype=search&searchText=[[searchString]+]
  8. SearchAndOpenRecords :
    1. Sample implementation using the API mentioned here.
      function retrieveMultipleAndOpenRecords(context, CifHostedControl, corrId, entityName, queryParameters, searchOnly){
      Xrm.WebApi.retrieveMultipleRecords(entityName, queryParameters).then(
      function(result){
      var res = { data : result.entities, entityName : entityName  };
      try{
      if(result.entities.length == 1){
      if(searchOnly == false){
      var res = result.entities[0];
      var formOptions = { entityName: entityName,
      entityId: res[entityName + "id"] };
      Xrm.Navigation.openForm(formOptions);
      }
      }
      else{
      if(searchOnly == false){
      Xrm.Navigation.navigateTo({
      pageType: "search",
      searchText:
      ExtractParameter(queryParameters, "$search"),
      searchType: 1,
      EntityNames: [entityName],
      EntityGroupName: ""});
      }
      }
      }
      catch(e){}
      // Resolve the pending promise in CIF if needed, you can use
      // notifyUSD like mentioned in RetrievRecord API
      },
      
      function(error){
      // Reject the pending promise in CIF if needed
      });
      }

      Pass the data that was received from the corresponding event in this RunXrmCommand call.

  9. GetEnvironment :
    1. In Web this data is passed by CIF library but inside Unified Service Desk we don’t have any context available to execute this. So it is left to the user on how to pass back the data.
    2. You can again do a RunXrmCommand action on some page that you are sure will be available at that time (I used it on Dashboard).
    3. Sample implementation :
      function getEnvironment(context, CifHostedControl, corrId){
      try{
      var pageUrl = new URL(eval("window.top.Xrm.Page.getUrl()"));
      console.log(pageUrl);
      var data = {};
      for(var entry of pageUrl.searchParams.entries()){
      data[entry[0]] = entry[1];
      }
      var cont = Xrm.Utility.getGlobalContext();
      data["clientUrl"] = encodeURIComponent(cont.getClientUrl());
      data["appUrl"] = encodeURIComponent(cont.getCurrentAppUrl());
      data["orgLcid"] = cont.organizationSettings.languageId;
      data["orgUniqueName"] = cont.organizationSettings.uniqueName;
      data["orgId"] = cont.organizationSettings.organizationId;
      data["userId"] = cont.userSettings.userId;
      data["userLcid"] = cont.userSettings.languageId;
      data["username"] = cont.userSettings.userName;
      data["crmVersion"] = cont.getVersion();
      
      var result = { data : encodeURIComponent(JSON.stringify(data)) };
      
      // Use the notifyUSD function with http://uii like shown in
      // previous sample to send this result back to CIF control.
      }
      catch(err){
      // Reject the pending promise in CIF control
      }
      }

NOTE :

Apart from the above mentioned approach for resolving the pending promises inside CIF control, you can directly fire the UpdateCifContext action call whenever required, the important part is to pass the same correlation Id (corrId) that you had received in the event so that the corresponding success or error functions are called.

Unified Interface Page (Client) Events:

There are some client-side events also which used to be raised in CIF control. Inside Unified Service Desk you can have multiple softphones opened at once, so it is not possible to determine automatically which control to pass these events to. So these events are raised on corresponding Unified Interface page with the required data and you can then raise these events on whichever CIF control you want by using RaiseCifClientEvent action call.

The parameters of this action call are :

event : the name of the event should be from the list as mentioned in addHandler (CIF JavaScript API Reference) (onclicktoact etc..)

data : the data should follow the format given in Events.

  1. onclicktoact : For this we raise an event OnClickToAct on Unified Interface page inside Unified Service Desk whenever it is triggered, on this you can hook an action call like mentioned above to pass the same event to the CIF control.
  2. onsendkbarticle : For this we raise an event OnSendKbArticle on Unified Interface page inside Unified Service Desk whenever it is triggered, on this you can hook an action call like mentioned above to pass the same event to the CIF control.
  3. onpagenavigate : You can use the NavigationRequested event on Unified Interface page control to raise this event on CIF control and pass the data as required.

The corresponding Unified Interface events can be found on Unified Interface Page (Hosted Control) page.

NOTE :

There are some APIs regarding the panel width, panel mode which are simply ignored inside Unified Service Desk as they are not applicable. Also settings regarding getClickToAct and setClickToAct are ignored, if you don’t want the data for clickToAct to be passed then just don’t fire the corresponding action call inside  Unified Service Desk.

 

(This blog has been authored by Aniket Marlapalle with the inputs from Deepa Patel and  Karthik Balasubramanian)

Skip to main content