Sending Batch Requests to Dynamics 365 Web API Using C#
Executing several CRUD operations in a single network call lowers latency and boosts performance when integrating with the Microsoft Dynamics 365 Web API. Batch requests, which are supported by the OData $batch endpoint, are used for this.
In addition to examining how to manage multipart responses in an organized and reusable manner, this blog will walk through the process of implementing batch requests step-by-step.
Prerequisites
Before we dive into code:
Step-by-Step Breakdown
1. Understand the Structure of a Batch Request
2. Create a Simple Batch Request (Basic Example)
string batchBoundary = "batch_" + Guid.NewGuid(); // unique boundary
var batchContent = new MultipartContent("mixed", batchBoundary);
string changeSetId = "changeset_" + Guid.NewGuid(); // unique changeset
var changeSetContent = new MultipartContent("mixed", changeSetId);
// Add a PATCH request to the changeset
var updateRequest = new HttpRequestMessage(HttpMethod.Patch, baseUrl + "/api/data/v9.1/accounts(AccountId)");
updateRequest.Content = new StringContent("{ \"name\": \"Updated Account Name\" }", Encoding.UTF8, "application/json");
changeSetContent.Add(updateRequest);
// Add changeset to batch
batchContent.Add(changeSetContent);
3. Send Batch Request Using HttpClient
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("OData-Version", "4.0");
client.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.PostAsync(baseUrl + "/api/data/v9.1/$batch", batchContent);
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
Reusable Batch Request Function
For larger systems, a reusable method is useful. Let’s walk through your SendBatchRequestAsync:
4. Construct Reusable Batch Sender
public static async Task<List<JObject>> SendBatchRequestAsync(
HttpClient httpClient,
List<HttpContent> listOfRequests,
ILogger log,
int count = 0,
string methodType = null)
✔ Key Responsibilities:
5. Handle Nested Multipart Response
Responses from batch are in multipart/mixed format. To process them:
MultipartMemoryStreamProvider body = await response.Content.ReadAsMultipartAsync();
List<HttpResponseMessage> responses = await ReadHttpContents(body, log);
6. Helper Method to Read HTTP Parts
public static async Task<List<HttpResponseMessage>> ReadHttpContents(MultipartMemoryStreamProvider body, ILogger log)
Responsibilities:
7. Deserialize Plain HTTP Content
If a content part isn’t a full HTTP response, you can still deserialize the stream manually into an HttpResponseMessage.
HttpResponseMessage responseMessage = DeserializeToResponse(await c.ReadAsStreamAsync(), log);
You can implement DeserializeToResponse using custom logic or libraries like HttpClientMock/manual parsing.
Example Use Case
You may need to:
This method helps you optimize by reducing the number of round trips to the server.
Best Practices
Summary
In this guide, you learned:
Ready-to-Use Template
You can package this logic into a utility class like DynamicsBatchHelper, making it reusable across microservices or Azure Functions.
how-to-build-batch-request-dynamics-365
By: Varun Chalamalasetty | varun@gmail.com | July 4, 2025, 6:34 a.m.
No answers yet.