CDS Debugging Proxy

Web proxy tool add-on for XrmToolBox to log all HTTP(S) traffic between your computer and CDS environment and/or any other internet portal. Inspect traffic, update on the fly, and fiddle with request/response.

Current version: 1.22.5.2020 (beta)

Key features:
* Override HTTP(s) Responses and Requests on the fly and directly in the text area with JS, HTML, CSS, JSON syntax highlight, and formatting.
* Detect and hook requests that contain FetchXML or Views and provides the possibility to test, change and execute them.
* Possibility to create a dedicated Chrome environment to avoid cashing and check your requests outside your standard browser configuration.
* Embedded JS engine to run custom scripts and as example update CDS metadata on the fly.
* Possibility to configure autoresponse for typical requests.
* Possibility to execute any requests manually.

cdsdp

Some usage examples:

1. Hook Fetch XML

Open the list of contacts and wait until it loaded, then click “Start Capture“. Try to switch between contact views. The system will send fetchXml requests depends on the view type. CDS Debugging Proxy will capture requests and show them in an appropriate view. Chose one of them which contains fetchXml and go “Hooked FetchXml” section to analyze it.

cdsafetch

This will also work for system views. So if the request contains ViewId the CDS debugging proxy will try to extract the fetchXML and show the view name.

2. Update action for the “Refresh” button on contact HomePageGrid only using a proxy server.

You should launch Chrome without caching to implement this. “No cache” button.

To start capturing data, click “Start Capture“. Open the list of contacts and put a filter to capture only HomePageGrid and Main_system_library.js. Use ‘;’ as a separator.

cdsfilter

First of all let’s review requests, we need to modify. We have two. First one is metadata request:

api/data/v9.0/GetClientMetadata(ClientMetadataQuery=@ClientMetadataQuery)?@ClientMetadataQuery={%22MetadataType%22%3A%22ribbon%22,%22MetadataSubtype%22%3Anull,%22EntityLogicalName%22%3A%22contact%22,%22MetadataId%22%3Anull,%22MetadataNames%22%3A[%22HomePageGrid%22],%22GetDefault%22%3Afalse,%22DependencyDepth%22%3A%22OnDemandWithoutContext%22,%22ChangedAfter%22%3A%222154182%22,%22Exclude%22%3A[],%22AppId%22%3A%223ed211b3-c292-ea11-a815-000d3a5916ef%22}&umv=2154182&mv=2695734&api-version=9.1

This request will return ribbons configuration for contact HomePageGrid.

We need to update the function.

cdsfunc

Second is the js file with the function which should be executed.

%7b637259916190017162%7d/webresources/Main_system_library.js

To update metadata is easier to use a script. Go to the Script section and past the following script.

function onProxyResponse() {
//check that we are in the right place
    if (CDSDP_ResponseBody.indexOf("Mscrm.Modern.refreshCommand") != -1 
		&& CDSDP_RequestUrl.indexOf("HomePageGrid") != -1)  {
            //parce metadata json from response body
            var obj = JSON.parse(CDSDP_ResponseBody);
            //extracting metadata section and parcing it
            var metadata = JSON.parse(obj["Metadata"]);
            //replacing standard function with 'TestRibbon'
            metadata.Ribbons[0].Commands.contact["Mscrm.Modern.refreshCommand"].
                            Actions[0].Attributes["FunctionName"] = "TestRibbon";
            //converting metadata json to string
            var ribbonMetadata = JSON.stringify(metadata);
            //replacing standard section with our variant
            obj["Metadata"] = ribbonMetadata;
            //updating output
            CDSDP_SetResponseBody(JSON.stringify(obj));
    }
    return true; // we show all list view items. 
};

Don’t forget to check “Use JS Script.”

cdsjsscipt1

This script will be executed for each response.

The next part is to add our function to Main_system_library.js. This is quite simple. Select the request in the list of requests and add the function on top of the file.

CdSupdateResponse

Don’t forget to check “Override response by URL”.

Next time when you refresh the page script will update metadata, and Js file will be replaced by our changes.

3. Downloading all images from Dynamics Marketing

Suppose you want to download all files from marketing content area. You can use CDS Debugging Proxy for this.  Just open the appropriate section in Dynamics Marketing.

dynmarketingfilespng

Then click “Start capture” in CDS Debugging Proxy and Refresh the page using the “Refresh” button from the ribbon.

You will capture fetchXml request which extracts all needed information about images.

/api/data/v9.0/msdyncrm_files?fetchXml=%3Cfetch%20version%3D%221.0%22%20mapping%3D%22logical%22%20returntotalrecordcount%3D%22true%22%20page%3D%221%22%20count%3D%2250%22%20no-lock%3D%22false%22%3E%3Centity%20name%3D%22msdyncrm_file%22%3E%3Cattribute%20name%3D%22statecode%22%2F%3E%3Cattribute%20name%3D%22modifiedon%22%2F%3E%3Cattribute%20name%3D%22msdyncrm_fileid%22%2F%3E%3Cattribute%20name%3D%22msdyncrm_name%22%2F%3E%3Cattribute%20name%3D%22msdyncrm_bloburi%22%2F%3E%3Cattribute%20name%3D%22msdyncrm_width%22%2F%3E%3Cattribute%20name%3D%22msdyncrm_thumbnail_url%22%2F%3E%3Cattribute%20name%3D%22msdyncrm_height%22%2F%3E%3Cattribute%20name%3D%22msdyncrm_blobsize%22%2F%3E%3Cattribute%20name%3D%22msdyncrm_contenttype%22%2F%3E%3Cattribute%20name%3D%22msdyncrm_blobcdnuri%22%2F%3E%3Cattribute%20name%3D%22createdon%22%2F%3E%3Corder%20attribute%3D%22createdon%22%20descending%3D%22true%22%2F%3E%3Cfilter%20type%3D%22and%22%3E%3Ccondition%20attribute%3D%22statecode%22%20operator%3D%22eq%22%20value%3D%220%22%2F%3E%3C%2Ffilter%3E%3C%2Fentity%3E%3C%2Ffetch%3E

The response of this request is the following JSON structure

{
  "@odata.context": "https://m365x373064.crm.dynamics.com/api/data/v9.0/$metadata#msdyncrm_files(msdyncrm_name,statecode,modifiedon,msdyncrm_fileid,msdyncrm_contenttype,createdon,msdyncrm_width,msdyncrm_bloburi,msdyncrm_blobcdnuri,msdyncrm_height,msdyncrm_thumbnail_url,msdyncrm_blobsize)",
  "@odata.count": 2,
  "@Microsoft.Dynamics.CRM.totalrecordcount": 2,
  "@Microsoft.Dynamics.CRM.totalrecordcountlimitexceeded": false,
  "value": [
    {
      "@odata.etag": "W/\"2183865\"",
      "msdyncrm_name": "img.png",
      "statecode@OData.Community.Display.V1.FormattedValue": "Active",
      "statecode": 0,
      "modifiedon@OData.Community.Display.V1.FormattedValue": "5/12/2020 12:31 PM",
      "modifiedon": "2020-05-12T12:31:30Z",
      "msdyncrm_fileid": "47fa427f-4c94-ea11-a811-000d3a59ff91",
      "msdyncrm_contenttype": ".png",
      "createdon@OData.Community.Display.V1.FormattedValue": "5/12/2020 12:31 PM",
      "createdon": "2020-05-12T12:31:27Z",
      "msdyncrm_width@OData.Community.Display.V1.FormattedValue": "768",
      "msdyncrm_width": 768,
      "msdyncrm_bloburi": "https://mktdplp102wuda.blob.core.windows.net/p-5c057baddc034b259b3528f3531e22e2/47fa427f-4c94-ea11-a811-000d3a59ff91/zLYhjqwFIC7uAOuqtZ--R7S6ZLIgN85sId7ewxfb5Lk!",
      "msdyncrm_blobcdnuri": "https://mktdplp102wuda.azureedge.net/org-5c057baddc034b259b3528f3531e22e2/47fa427f-4c94-ea11-a811-000d3a59ff91/zLYhjqwFIC7uAOuqtZ--R7S6ZLIgN85sId7ewxfb5Lk!",
      "msdyncrm_height@OData.Community.Display.V1.FormattedValue": "768",
      "msdyncrm_height": 768,
      "msdyncrm_thumbnail_url": "https://mktdplp102wuda.blob.core.windows.net/org-5c057baddc034b259b3528f3531e22e2/47fa427f-4c94-ea11-a811-000d3a59ff91/zLYhjqwFIC7uAOuqtZ--R7S6ZLIgN85sId7ewxfb5Lk!-160x120",
      "msdyncrm_blobsize@OData.Community.Display.V1.FormattedValue": "152,728",
      "msdyncrm_blobsize": 152728
    },
    {
      "@odata.etag": "W/\"2183861\"",
      "msdyncrm_name": "img.png",
      "statecode@OData.Community.Display.V1.FormattedValue": "Active",
      "statecode": 0,
      "modifiedon@OData.Community.Display.V1.FormattedValue": "5/12/2020 12:31 PM",
      "modifiedon": "2020-05-12T12:31:11Z",
      "msdyncrm_fileid": "8e47c973-4c94-ea11-a811-000d3a59ff91",
      "msdyncrm_contenttype": ".png",
      "createdon@OData.Community.Display.V1.FormattedValue": "5/12/2020 12:31 PM",
      "createdon": "2020-05-12T12:31:07Z",
      "msdyncrm_width@OData.Community.Display.V1.FormattedValue": "768",
      "msdyncrm_width": 768,
      "msdyncrm_bloburi": "https://mktdplp102wuda.blob.core.windows.net/p-5c057baddc034b259b3528f3531e22e2/8e47c973-4c94-ea11-a811-000d3a59ff91/9gE0X1AZPpkk9ebgMoIorOAXHL_M0fcVkpLVuVugEdA!",
      "msdyncrm_blobcdnuri": "https://mktdplp102wuda.azureedge.net/org-5c057baddc034b259b3528f3531e22e2/8e47c973-4c94-ea11-a811-000d3a59ff91/9gE0X1AZPpkk9ebgMoIorOAXHL_M0fcVkpLVuVugEdA!",
      "msdyncrm_height@OData.Community.Display.V1.FormattedValue": "768",
      "msdyncrm_height": 768,
      "msdyncrm_thumbnail_url": "https://mktdplp102wuda.blob.core.windows.net/org-5c057baddc034b259b3528f3531e22e2/8e47c973-4c94-ea11-a811-000d3a59ff91/9gE0X1AZPpkk9ebgMoIorOAXHL_M0fcVkpLVuVugEdA!-160x120",
      "msdyncrm_blobsize@OData.Community.Display.V1.FormattedValue": "127,704",
      "msdyncrm_blobsize": 127704
    }
  ]
}

The next step for us should be to parce this structure and download the files according to the links. Go to “Script” section and past following script

function onProxyResponse() {
    var json = JSON.parse(CDSDP_ResponseBody);
    CDSDP_ClearLog();
    CDSDP_Log("Downloading files...");
    for(var i=0;i<json.value.length;i++){
        CDSDP_Log(json.value[i]["msdyncrm_name"]+" : "+json.value[i]["msdyncrm_bloburi"]);
        CDSDP_DownloadFileFormWeb(json.value[i]["msdyncrm_blobcdnuri"],"C:\\marketingimgs\\"+i+json.value[i]["msdyncrm_name"]);
    }
    return true;
};

Don’t forget to check “Use JS script”.  Next time you click “Refresh” button in your Dynamics Marekting app, the system will send the same request and the script will parce the response and download files to provided folder C:\marketingimgs\

dmfilesdow