Crafting Multipart/Form-Data Requests in Business Central
In today's interconnected digital landscape, mastering the art of web service calls is essential for seamless integration and automation within enterprise systems. Microsoft Dynamics 365 Business Central, with its robust capabilities, empowers users to effortlessly interact with external services through RESTful APIs. In this blog post, we'll embark on a journey to demystify the process of crafting these calls, using Postman as our trusty ally for testing and fine-tuning.
As we delve into the intricacies of crafting these calls, we'll explore how to effectively utilize Postman, a versatile API testing tool, to verify and refine our requests against the designated endpoints. With Postman by our side, we'll ensure that our requests are structured correctly and yield the desired results.
But our quest doesn't end there. To gain deeper insights into the inner workings of these requests, we'll enlist the assistance of requestinspector.com—a powerful tool for analyzing HTTP requests and responses. By scrutinizing the intricacies of our requests through requestinspector.com, we'll gain valuable insights into how Postman constructs the request forms, shedding light on the underlying mechanics of our interactions with external services.
While Postman and requestinspector.com serve as invaluable aids in our journey, we'll also navigate the nuances of crafting requests directly within Business Central. Here, we'll employ different approaches to create request forms tailored to the platform's unique requirements. Armed with our knowledge and expertise, we'll seamlessly bridge the gap between Business Central and external services, enabling seamless data exchange and automation.
But what about security? It's a paramount concern in today's interconnected world. To ensure the integrity and confidentiality of our data, we'll leverage the "Cryptography Management" codeunit in Business Central. By utilizing cryptographic hashing algorithms such as SHA-256, we can securely generate hash values from different parameters, safeguarding sensitive information during transit.
In our journey, we'll demonstrate how to create a pre-request script in Postman to calculate the SHA-256 hash of our parameters and output the result to the console. Then, armed with the knowledge of the expected hash value, we'll replicate the process within Business Central. By invoking the "Cryptography Management" codeunit and calling the appropriate functions, we'll generate the SHA-256 hash and compare it with the result from Postman. Through meticulous validation and verification, we'll ensure that our cryptographic implementations are accurate and consistent across platforms.
Join us as we embark on this transformative journey into the realm of web service calls in Business Central. Together, we'll unlock the full potential of integration and automation, while prioritizing the security and integrity of our data.
Let’s deep-dive
Install Postman
If you haven't already, download and install Postman from the official website (https://www.postman.com/).
Create a New Request
Open Postman and create a new request by clicking on the "New" button in the top-left corner and selecting "Request".
Specify Request Details
Enter the URL of the final endpoint you want to interact with in the request URL field.
Choose the appropriate HTTP method (GET or POST) based on the endpoint's requirements. In this example we will use POST
Add Parameters (if applicable): If your endpoint requires parameters, you can add them in the "Params" tab for GET requests or in the "Body" tab for POST requests.
Test the Request: Click on the "Send" button to execute the request and verify that you receive the expected response from the endpoint. Postman will display the response body, headers, and other relevant information.
Verify Response: Review the response data to ensure it aligns with your expectations. This step confirms that the endpoint is reachable and responds correctly to your requests.
Once you've successfully tested the endpoint using Postman and received the expected response, you can proceed with replicating the same request in Business Central. This process typically involves constructing the request payload, handling authentication, and processing the response within Business Central's environment.
If you encounter any issues during testing or need assistance with specific aspects of setting up Postman or configuring requests, feel free to ask for help!
Time to analyze the requests
RequestInspector can provide valuable insights into the details of the HTTP request and response exchanged between Postman and your endpoint. Here's how you can analyze the call using RequestInspector:
Capture the Request
In Postman, change the address to Requestinspectors URL.
Inspect the Request in RequestInspector: Once you've sent the request, go to RequestInspector (https://requestinspector.com/) in your web browser.
Find the Request
You should see your request listed on the RequestInspector dashboard. Click on it to view more details.
Analyze Request Headers and Body
RequestInspector will display the details of the request, including headers, body, method, URL, etc. This information can clarify how Postman constructs the request.
Inspect the Response (if applicable): If your endpoint returns a response, you can also inspect it in RequestInspector. This allows you to see the full exchange between Postman and the endpoint.
By analyzing the request and response in RequestInspector, you can gain insights into how Postman interacts with the endpoint, including details such as headers, authentication methods, and request parameters. This information will be valuable when replicating the same call in Business Central.
If you encounter any unexpected behavior or discrepancies during analysis, RequestInspector can help you pinpoint the issue and make necessary adjustments to your request setup in Postman or your endpoint configuration.
Now we now how Postman interacts with the endpoint.
Let’s go AL and create some functions.
In this case, I will write a codeunit were putting all the requested stuff.
Generating a Unique Boundary
Our journey begins with the creation of a unique boundary string, a crucial element in multipart/form-data requests. Through a meticulous process of GUID concatenation, character removal, and padding, we craft a distinct identifier that ensures proper segmentation of request parts.
Function GenerateRandomBoundary
local procedure GenerateRandomBoundary() boundary: Textbeginboundary := CreateGuid() + CreateGuid() + CreateGuid();boundary := DELCHR(boundary, '=', '{}-ABCDEFGHIJKLMNOPQRSTUVWXYZ');boundary := COPYSTR(boundary, 1, 24);boundary := PadStr('', 50 - strlen(boundary), '-') + boundary;exit(boundary);end;
function BuildWebRequest
procedure BuildWebRequest()varHTTPClient: HttpClient;HTTPRequestMsg: HttpRequestMessage;HTTPResponseMsg: HttpResponseMessage;HTTPContent: HttpContent;Requestheaders: HttpHeaders;HttpHeaders: HttpHeaders;textBuilder: TextBuilder;sha256: Text;AuthenticationText: Text;boundary: Text;MsgText: Text;beginboundary := GenerateRandomBoundary();textBuilder.AppendLine(FormatBounderyForForm(boundary, FormatBoundery::Open));textBuilder.AppendLine('Content-Disposition: form-data; name="endpoint"');textBuilder.AppendLine('');textBuilder.AppendLine(AllnetIntegrationSetup."Order Endpoint");textBuilder.AppendLine(FormatBounderyForForm(boundary, FormatBoundery::Open));textBuilder.AppendLine('Content-Disposition: form-data; name="action"');textBuilder.AppendLine('');textBuilder.AppendLine(AllnetIntegrationSetup."Action get Orders");textBuilder.AppendLine(FormatBounderyForForm(boundary, FormatBoundery::Open));textBuilder.AppendLine('Content-Disposition: form-data; name="user"');textBuilder.AppendLine('');textBuilder.AppendLine('nordic');textBuilder.AppendLine(FormatBounderyForForm(boundary, FormatBoundery::Open));textBuilder.AppendLine('Content-Disposition: form-data; name="secure"');textBuilder.AppendLine('');textBuilder.AppendLine(GenerateSha256Hash(AuthenticationText));textBuilder.AppendLine(FormatBounderyForForm(boundary, FormatBoundery::Close));
HTTPContent.WriteFrom(textBuilder.Totext());HTTPContent.GetHeaders(HttpHeaders);
if HttpHeaders.Contains('Content-Type') thenHttpHeaders.Remove('Content-Type');HttpHeaders.Add('Content-Type', 'multipart/form-data; boundary=' + boundary);
HTTPRequestMsg.Content := HTTPContent;HTTPRequestMsg.GetHeaders(Requestheaders);Requestheaders.Add('Accept', '*/*');HTTPRequestMsg.SetRequestUri(AllnetIntegrationSetup."API Address");HTTPRequestMsg.Method(action);HTTPClient.Post(AllnetIntegrationSetup."API Address", HTTPContent, HTTPResponseMsg);
if HTTPResponseMsg.IsSuccessStatusCode() then beginHTTPResponseMsg.Content.ReadAs(MsgText);ImportOrder.ReadJSONOrder(MsgText);end elseError(format(HTTPResponseMsg.HttpStatusCode()));end;
Constructing the Request Body
Armed with our boundary, we embark on assembling the body of our HTTP request. Using a TextBuilder, we meticulously append each parameter-value pair, adhering to the multipart/form-data format. From endpoint details to authentication tokens, every element finds its place in this digital canvas.
Embracing Best Practices
As we navigate through the code, we encounter best practices that elevate our craftsmanship. From sanitizing boundary strings to utilizing built-in functions for cryptographic hashing, our approach prioritizes efficiency, security, and compliance.
Navigating the Tools of the Trade
In our toolkit lies an array of invaluable resources. From HttpClient instances to HttpRequestMessage objects, each component plays a pivotal role in orchestrating our HTTP request. Through careful orchestration, we harness the power of these tools to navigate the digital landscape seamlessly.
Empowering Integration with External Services
At its core, our endeavor is about bridging the gap between Business Central and external ecosystems. With our multipart/form-data request poised for deployment, we stand ready to unlock a world of possibilities—from data synchronization to process automation.