How to send raw bytes over the http wire:
var binaryContent = new ByteArrayContent(new byte[] { 1, 2, 3 });
binaryContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
content.Add(binaryContent, "content");
var result = await client.PostAsync("api/bytes/incoming", content);
The trick is that the receiver must be aware of "ContentType: application/octet-stream" which is not default for most web servers. So the server side requires a little more effort:
public class RawRequestBodyFormatter : InputFormatter
{
public RawRequestBodyFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/octet-stream"));
}
/// <summary>
/// Allow text/plain, application/octet-stream and no content type to
/// be processed
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override Boolean CanRead(InputFormatterContext context)
{
if (context == null) throw new ArgumentNullException(nameof(context));
var contentType = context.HttpContext.Request.ContentType;
if (string.IsNullOrEmpty(contentType) || contentType == "text/plain" ||
contentType == "application/octet-stream")
return true;
return false;
}
/// <summary>
/// Handle text/plain or no content type for string results
/// Handle application/octet-stream for byte[] results
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
var request = context.HttpContext.Request;
var contentType = context.HttpContext.Request.ContentType;
if (string.IsNullOrEmpty(contentType) || contentType == "text/plain")
{
using (var reader = new StreamReader(request.Body))
{
var content = await reader.ReadToEndAsync();
return await InputFormatterResult.SuccessAsync(content);
}
}
if (contentType == "application/octet-stream")
{
using (var ms = new MemoryStream(2048))
{
await request.Body.CopyToAsync(ms);
var content = ms.ToArray();
return await InputFormatterResult.SuccessAsync(content);
}
}
return await InputFormatterResult.FailureAsync();
}
}
and at Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(o => o.InputFormatters.Insert(0, new RawRequestBodyFormatter()));
}
and the controller
[HttpPost]
[Route("api/bytes/incoming")]
public byte[] RawBytesFormatter([FromBody] byte[] rawData)
{
return rawData;
}
I took the server-side snippets from Rick Strahl excellent blog post about this: https://weblog.west-wind.com/posts/2017/Sep/14/Accepting-Raw-Request-Body-Content-in-ASPNET-Core-API-Controllers?Page=2