title: OData V4 batch request 'Content-ID' was not present in the header
body: <p>Our OData endpoint is self-hosted(OWIN). For single request: creating, updating, patching and deleting everything works great, but the problem is when I send batch request.
  I read a lot of articles, but still cannot solve the issue.
  In OData documentation it says:
  My question is: How can I set 'Content-ID' to batch request's header?</p>
  
  <p>In endpoint Batch is enabled:</p>
  
  <pre><code>HttpConfiguration config = new HttpConfiguration();
  var odataBatchHandler = new DefaultODataBatchHandler(new HttpServer(config));
  config.MapODataServiceRoute("ODataApi", null, builder.GetEdmModel(), odataBatchHandler);
  config.Count().Filter().OrderBy().Expand().MaxTop(null).Select();
  appBuilder.UseWebApi(config);
  </code></pre>
  
  <p>Here is the test: </p>
  
  <pre><code> [TestMethod]
          public void BatchRequestTest()
          {
              var odataAddress = "https://localhost:23170/Sample/Sample/OData/";
              var batchUrl = $"{odataAddress}$batch";
              HttpClient http = new HttpClient();
  
              // Global batch request
              HttpRequestMessage batchRequest = new HttpRequestMessage(HttpMethod.Post, batchUrl);
              batchRequest.Headers.Authorization = new AuthenticationHeaderValue("Basic", "QWRtaW5pc3RyYXRvcjpwdw==");
              MultipartContent batchContent = new MultipartContent("mixed", "batch_" + Guid.NewGuid().ToString());
  
              // Third element: POST user creation
              // 1: a multipart content that represents the changeset container
              MultipartContent changeSet = new MultipartContent("mixed", "changeset_" + Guid.NewGuid().ToString());
              // 2: one request message object per post request
              HttpRequestMessage postRequest = new HttpRequestMessage(HttpMethod.Post, $"{odataAddress}/SATeacher");
              postRequest.Headers.Authorization = new AuthenticationHeaderValue("Basic", "QWRtaW5pc3RyYXRvcjpwdw==");
  
              postRequest.Content = new StringContent("", Encoding.UTF8, "application/json");
              // 3: one message content per corresponding post request
              HttpMessageContent postRequestContent = new HttpMessageContent(postRequest);
              postRequestContent.Headers.Remove("Content-Type");
              postRequestContent.Headers.Add("Content-Type", "application/http");
              postRequestContent.Headers.Add("Content-Transfer-Encoding", "binary");
              // Add this POST content to the changeset
              changeSet.Add(postRequestContent);
              // Add the changeset to the batch content
              batchContent.Add(changeSet);
  
              // Here we go
              batchRequest.Content = batchContent;
              HttpResponseMessage response = http.SendAsync(batchRequest).Result;
              var responseString = response.Content.ReadAsStringAsync().Result;
          }
  </code></pre>
  
  <p>Here is an exception:</p>
  
  <p>{"Message":"An error has occurred.","ExceptionMessage":"The header with name 'Content-ID' was not present in the header collection of the batch operation.","ExceptionType":"Microsoft.OData.ODataException","StackTrace":"   at Microsoft.OData.ODataBatchReader.CreateOperationRequestMessageImplementation()\r\n   at Microsoft.OData.ODataBatchReader.InterceptException[T](Func<code>1 action)\r\n   at Microsoft.OData.ODataBatchReader.CreateOperationRequestMessage()\r\n   at System.Web.OData.Batch.ODataBatchReaderExtensions.&lt;ReadOperationInternalAsync&gt;d__6.MoveNext() in C:\\Builds\\Eagle\\Eagle\\Framework\\Server\\OData\\Source\\System.Web.OData\\OData\\Batch\\ODataBatchReaderExtensions.cs:line 149\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter</code>1.GetResult()\r\n   at System.Web.OData.Batch.ODataBatchReaderExtensions.d__1.MoveNext() in C:\Builds\Eagle\Eagle\Framework\Server\OData\Source\System.Web.OData\OData\Batch\ODataBatchReaderExtensions.cs:line 63\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter<code>1.GetResult()\r\n   at System.Web.OData.Batch.DefaultODataBatchHandler.&lt;ParseBatchRequestsAsync&gt;d__3.MoveNext() in C:\\Builds\\Eagle\\Eagle\\Framework\\Server\\OData\\Source\\System.Web.OData\\OData\\Batch\\DefaultODataBatchHandler.cs:line 141\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter</code>1.GetResult()\r\n   at System.Web.OData.Batch.DefaultODataBatchHandler.d__1.MoveNext() in C:\Builds\Eagle\Eagle\Framework\Server\OData\Source\System.Web.OData\OData\Batch\DefaultODataBatchHandler.cs:line 44\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Batch.HttpBatchHandler.d__0.MoveNext()"}</p>
  
  <p>Getting exception in line: HttpResponseMessage response = http.SendAsync(batchRequest).Result;</p>
  
  <p>Any ideas?</p>
  
  <p>Thanks in advance,</p>