I want to post this data to Web API server:
public sealed class SomePostRequest { public int Id { get; set; } public byte[] Content { get; set; } }
Using this code for server:
[Route("Incoming")] [ValidateModel] public async Task<IHttpActionResult> PostIncomingData(SomePostRequest requestData) { // POST logic here }
and this - for client:
var client = new HttpClient(); client.BaseAddress = new Uri("http://localhost:25001/"); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json")); var content = new FormUrlEncodedContent(new Dictionary<string, string> { { "id", "1" }, { "content", "123" } }); var result = await client.PostAsync("api/SomeData/Incoming", content); result.EnsureSuccessStatusCode();
everything works fine (at least, debugger stops at breakpoint in PostIncomingData
).
Since there is a byte
array, I don't want to serialize it as JSON, and want to post it as binary data to decrease network traffic (something like application/octet-stream
).
How this can be achieved?
I've tried to play with MultipartFormDataContent
, but looks like I just can't understand, how MultipartFormDataContent
will match signature of controller's method.
E.g., replacing content to this:
var content = new MultipartFormDataContent(); content.Add(new FormUrlEncodedContent(new Dictionary<string, string> { { "id", "1" } })); 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/SomeData/Incoming", content); result.EnsureSuccessStatusCode();
leads to error 415 ("Unsupported media type").
WebAPI v2.1 and beyond supports BSON (Binary JSON) out of the box, and even has a MediaTypeFormatter
included for it. This means you can post your entire message in binary format.
If you want to use it, you'll need to set it in WebApiConfig
:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Formatters.Add(new BsonMediaTypeFormatter()); } }
Now, you an use the same BsonMediaTypeFormatter
at the client side to serialize your request:
public async Task SendRequestAsync() { var client = new HttpClient { BaseAddress = new Uri("http://www.yourserviceaddress.com"); }; // Set the Accept header for BSON. client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/bson")); var request = new SomePostRequest { Id = 20, Content = new byte[] { 2, 5, 7, 10 } }; // POST using the BSON formatter. MediaTypeFormatter bsonFormatter = new BsonMediaTypeFormatter(); var result = await client.PostAsync("api/SomeData/Incoming", request, bsonFormatter); result.EnsureSuccessStatusCode(); }
Or, you can use Json.NET to serialize your class to BSON. Then, specify you want to use "application/bson" as your "Content-Type":
public async Task SendRequestAsync() { using (var stream = new MemoryStream()) using (var bson = new BsonWriter(stream)) { var jsonSerializer = new JsonSerializer(); var request = new SomePostRequest { Id = 20, Content = new byte[] { 2, 5, 7, 10 } }; jsonSerializer.Serialize(bson, request); var client = new HttpClient { BaseAddress = new Uri("http://www.yourservicelocation.com") }; client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/bson")); var byteArrayContent = new ByteArrayContent(stream.ToArray()); byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("application/bson"); var result = await client.PostAsync( "api/SomeData/Incoming", byteArrayContent); result.EnsureSuccessStatusCode(); } }
I convert Byte Array
into Base64 String
to post:
await client.PostAsJsonAsync( apiUrl, new { message = "", content = Convert.ToBase64String(yourByteArray), } );
and receiver can convert the Base64 String
back to Byte Array
by:
string base64Str = (string)postBody.content; byte[] fileBytes = Convert.FromBase64String(base64Str);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With