Recently, we were faced with the challenge of checking what our D365FO environment was sending and receiving over HTTPS protocol on the Internet and why the integration with external services such as Microsoft Office or SharePoint Online was not working. In order to solve the problem at hand, we decided to intercept the HTTP traffic and check the URLs, sent and received headers, and the body (contents). The same technique can be used when exploring how to create your own customizations by calling the existing services that are already present in the D365FO and cannot be extended using the standard APIs.
In this article we describe in detail how to achieve such a scenario on the D365FO OneBox development machine.
The easiest way to do this is to set up a web debugging proxy tool, such as Telerik Fiddler, that sits between your computer and the Internet and captures incoming and outgoing HTTP traffic between the two. You can use the tool to examine the traffic and perform modifications, if necessary. However, the main problem here is that the traffic is encrypted, and you need to decrypt it, capture it, and then resend it to the destination service.
In this article, we will first show you how to configure Fiddler and then, on the example, examine the traffic and implement your own solution. The same procedure can be applied to detect problems in the standard D365FO functionality.
Install & Configure Telerik Fiddler on your D365FO
There are several versions of the Telerik Fiddler debugging tool, and we used Fiddler Classic for the purpose of this article. You can download and install Fiddler on your D365FO OneBox computer here.
After the installation is complete, open Fiddler and follow the steps described below to decrypt, inspect, and encrypt the traffic sent to and received back from your computer to the Internet:
- Open the Tools > Options menu
- Click on the tab HTTPS
- Enable the Capture HTTPS CONNECTs option
- Enable Decrypt HTTPS traffic option
- Confirm the Windows reconfiguration of the Trusted CA list
- Make sure you have accepted to install the Fiddlers certificate, as it acts as a man-in-the-middle to capture HTTPS traffic.
- Confirm all the next dialogs
- Click the OK button and Fiddler is now ready to decrypt, intercept and encrypt all the HTTPS traffic.
- Start the tracing by pressing F12 function key.
Now, that Fiddler is properly configured and running, we can enable redirection of D365FO OneBox traffic to the Fiddler’s proxy server, which by default runs at http://localhost:8888.
The easiest way is to go to the D365FO web.config file, which by default is located at c:\AOSService\webroot\web.config, and add the following configuration to the <system.net> XML node:
<proxy proxyaddress="http://127.0.0.1:8888" />
If you set everything up as described above, you should now see quite a bit of traffic in the Fiddler, and it’s difficult to detect just the requests from the D365FO. You need to change the capturing filter from “All Processes” to “Non-Browser“. The capturing filter “Non-Browser” only captures traffic from the background services, and in this case, those called from your D365FO environment. After changing the capturing filter, press “Ctrl+X” to clear all the captured traffic and start testing the calls in the D365FO.
In the following example, we will try to figure out how the conversion of the generated document from Electronic Reporting to PDF works, and what services are called to accomplish this scenario. Once we get the answer, we will try to implement our solution to convert any Microsoft Word or Microsoft Excel document to PDF format.
In our example, we use the Sales Invoice document. Here you can download all the configurations and import them into your environment. If you did everything as expected, you should have the following ER configuration set up in your environment, as shown in the following image.
Once you have imported the configurations, you need to define all the possible Electronic Reporting destination testing scenarios as follows:
- Test Scenario #1 » Show the Sales Invoice on-screen print destination for Microsoft Word conversion to PDF
- Test Scenario #2 » Show the Sales Invoice on-screen print destination for Microsoft Excel with conversion to portrait PDF layout
- Test Scenario #3 » Show the Sales Invoice on-screen print destination for Microsoft Excel with conversion to landscape PDF layout
Intercepting D365FO Calls
Now, that our environment is properly set up, we can start intercepting the calls from the D365FO environment. After we have printed the Sales Invoices for all the before mentioned possible output scenarios, we have detected the following HTTP API calls:
- Request authentication OAuth2 token for resource https://configure.global.dynamics.com from Azure AD (https://login.windows.net/docentric.com/oauth2/token).
- Request authentication API key from https://apikeys.configure.global.dynamics.com for Microsoft Office Online Service.
- Convert Word file to PDF by using Microsoft Word Online Service (https://wordcs.officeapps.live.com/document/export/pdf?input=docx).
- Convert Excel file to PDF by using Microsoft Excel Online Service with Portrait page orientation (https://excelcs.officeapps.live.com/document/export/pdf?input=xlsx&printOption=1;-1;2;0).
- Convert Excel file to PDF by using Microsoft Excel Online Service with Landscape page orientation (https://excelcs.officeapps.live.com/document/export/pdf?input=xlsx&printOption=2;-1;2;0).
If we dig deeper into the Fiddler’s results, we can see, what kind of requests and responses were made and find out how we could implement these principles into our solution (Word or Excel file to PDF conversion by using Microsoft Office Online Conversion Service). We can skip authorization calls and focus on the conversion.
Test Scenario #1 » Convert Word to PDF
In Fiddler, we will first open the request and response shown on the next picture of the Microsoft Word to a PDF file conversion. The request is highlighted in the following picture.
In order to understand the request and response contents, we need to use the Fiddler’s Interceptors tab. Let’s now analyze and try to explain the relevant information, which can help us to understand, what is being called and returned from the Microsoft Office Conversion API.
We will explain the request and response contents in the following table:
The API call requires query string parameter input with the docx value.
|Body||Binary content of the Microsoft Word file to be converted to PDF.|
|Body||Represents the binary contents of the converted PDF file.|
Test Scenario #2 » Convert Excel File to PDF in Portrait Layout
Let us now analyze the request and response used to convert Microsoft Excel to a PDF file in a portrait orientation (see on next picture). As we can see immediately from the request URL, the API requires information about the page orientation used to convert to a PDF format.
A detailed analysis of the request and response gives us the following relevant information, displayed in the following table:
The API call requires the following query string parameters:
|Body||The binary contents of the Microsoft Excel file to be converted to a PDF format.|
|Body||Represents the binary contents of the converted PDF file.|
Test Scenario #3 » Convert Excel File to PDF in Landscape Layout
And finally, for the last scenario, we converted Microsoft Excel to a PDF using landscape page layout.
The request and response are the same as in test scenario #2. The only difference is in the URL query string parameters. The first value in the query string parameter printOption contains the value 2 and represents the landscape page orientation (https://excelcs.officeapps.live.com/document/export/pdf?input=xlsx&printOption=2;-1;2;0).
The Reverse-Engineered Custom Solution
Now it’s time to write our sample solution in X++,call the Microsoft Office conversion service and apply what we have learned from the HTTP traffic analysis.
For simplicity purpose, we created a runnable class called DocOfficeConversionService_POC, that can be executed with the following URL calls from your OneBox D365FO environment:
- Convert Microsoft Word to a PDF file » https://usnconeboxax1aos.cloud.onebox.dynamics.com/?cmp=usmf&mi=SysClassRunner&cls=DocOfficeConversionService_POC&args=docx
- Convert Microsoft Excel to a PDF file with page orientation Portrait » https://usnconeboxax1aos.cloud.onebox.dynamics.com/?cmp=usmf&mi=SysClassRunner&cls=DocOfficeConversionService_POC&args=xlsx;Portrait
- Convert Microsoft Excel to a PDF file with page orientation Landscape » https://usnconeboxax1aos.cloud.onebox.dynamics.com/?cmp=usmf&mi=SysClassRunner&cls=DocOfficeConversionService_POC&args=xlsx;Landscape
The solution consists of two parts:
- Part 1 » Request Service 2 Service Azure AD authorization token
- Part 2 » Prepare and send the request to convert Word or Excel to PDF
Part 1 » Request Service 2 Service Azure AD authorization token
In order to use the Office Conversion Service, we must first authenticate our request. For this purpose, we use the internal D365FO Azure AD Service 2 Service authentication method rather than the authorization key used in the standard Electronic Reporting Framework implementation. The key is retrieved from Dynamics Globalization Service.
/// Get access to for Service 2 Service AAD authentication
/// <returns>The access token header string.</returns>
internal static str getAccessToken()
// get current site url
IApplicationEnvironment env = EnvironmentFactory::GetApplicationEnvironment();
str currentSiteUrl = env.Infrastructure.HostUrl;
// get the authorization token - if you want to remove internal use only warning use reflection
var tokenGetter = new AADServiceTokenGetterConfiguration('S2SCertThumbprint');
var token = tokenGetter.GetToken(currentSiteUrl, null);
// return the access token header string (e.g., bearer xxxx)
return strFmt('%1 %2', token.AccessTokenType, token.AccessToken);
Part 2 » Prepare and send the request to convert Word or Excel to PDF
Now that we know how to authenticate in the Office Conversion Service, we can prepare the request with the appropriate query parameters, headers, and body with the binary source file to be converted to a PDF. For simplicity purpose, we will use two sample resource files (Word and Excel) for in the following example.
WebRequest request = WebRequest::Create(serviceUri);
// define the request headers
guid requestCorrelationId = newGuid();
str clientName = 'Docentric AX Office 2 PDF Client';
WebHeaderCollection requestHeaders = request.Headers;
// correlation Id is returned back from server for logging & finalization purposes
// authorization header
// client name - can be anything
// define the contect type & HTTP method
request.ContentType = DocOfficeConversionService_POC::getMimeType(extension);
request.Method = 'POST';
// define the destination filename
Filename destinationFilename = strFmt('Sales-Invoice-From-%1-%2.%3', extension, System.Guid::NewGuid().ToString('N'), PdfFileExtension);
// get the WEB request stream
using (Stream requestStream = request.GetRequestStream())
// read a sample Word or Excel file from resource
using (Stream sourceStream = MetadataSupport::GetResourceContentStream(DocOfficeConversionService_POC::getResourceFile(extension)))
// get the WEB response
using (WebResponse response = request.GetResponse())
// get the WEB response stream (converted filed)
using (Stream responseStream = response.GetResponseStream())
// prepare the Memory stream to be sent to client
using (MemoryStream destinationStream = new MemoryStream())
// copy the resulting PDF file to memory stream
// reset the position to the file beggining
destinationStream.Position = 0;
// send the file to user via browser – to simplify the download the file operation we will use Docentric DocFileMngHelper
DocFileMngHelper::sendFileToUser(destinationStream, destinationFilename, '', '', '', classStr(DocFileUploadTemporaryStorageStrategy), true, true, false);
Final Thoughts and Ideas for Improvement
Life can get a lot easier for an X++ developer if you can figure out what’s going on in the background and what D365FO is doing. If you use Fiddler as a man-in-the-middle, you can find out many exciting things and how to use what is already there in D365FO to achieve scenarios you may not even know you can do and use the functionality in your solutions. In this article the solution is just an example, but you can still use it for conversion and improve it with the following upgrades:
- Make it a generic solution to convert any Word or Excel file to PDF
- Cache the authentication token for a short period of time, or at least until it expires
- Implement more robust exception handling
If you have any new ideas or discoveries, please share them as well.