For more direct control over the payload you send, you can create derived HttpContent classes instead of letting your object be passed to an ObjectContent class which then delegates streaming to a Formatter class.
A JsonContent class that supports both reading and writing looks like this,
public class JsonContent : HttpContent
{
private readonly Stream _inboundStream;
private readonly JToken _value;
public JsonContent(JToken value)
{
_value = value;
Headers.ContentType = new MediaTypeHeaderValue("application/json");
}
public JsonContent(Stream inboundStream)
{
_inboundStream = inboundStream;
}
public async Task<JToken> ReadAsJTokenAsync()
{
return _value ?? JToken.Parse(await ReadAsStringAsync());
}
protected async override Task<Stream> CreateContentReadStreamAsync()
{
return _inboundStream;
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
if (_value != null)
{
var jw = new JsonTextWriter(new StreamWriter(stream)) {Formatting = Formatting.Indented};
_value.WriteTo(jw);
jw.Flush();
} else if (_inboundStream != null)
{
return _inboundStream.CopyToAsync(stream);
}
return Task.FromResult<object>(null);
}
protected override bool TryComputeLength(out long length)
{
length = -1;
return false;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_inboundStream.Dispose();
}
base.Dispose(disposing);
}
}
Once you have this class you can then do,
var content = new JsonContent(myObject);
_httpClient.PostAsync(uri,content);
If you need to change any of the content Headers you can do that manually before sending the request. And if you need to mess with any of the request headers then you use the SendAsync overload,
var content = new JsonContent(myObject);
// Update Content headers here
var request = new HttpRequestMessage {RequestUri = uri, Content = content };
// Update request headers here
_httpClient.SendAsync(request);
Derived content classes are easy to create for pretty much any media type or any source of data. I've created all kinds of classes derived from HttpContent. e.g. FileContent, EmbeddedResourceContent, CSVContent, XmlContent, ImageContent, HalContent, CollectionJsonContent, HomeContent, ProblemContent.
Personally, I've found it gives me much better control over my payloads.