tutorial net desde consumir consume asp c# asp.net-web-api asp.net-web-api2 dotnet-httpclient

net - web api json c#



Publicar una matriz de bytes en el servidor de la API web utilizando HttpClient (4)

Quiero publicar estos datos en el servidor web API:

public sealed class SomePostRequest { public int Id { get; set; } public byte[] Content { get; set; } }

Usando este código para el servidor:

[Route("Incoming")] [ValidateModel] public async Task<IHttpActionResult> PostIncomingData(SomePostRequest requestData) { // POST logic here }

y esto - para el cliente:

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();

todo funciona bien (al menos, el depurador se detiene en el punto de interrupción en PostIncomingData ).

Dado que hay una matriz de byte , no quiero serializarla como JSON, y quiero publicarla como datos binarios para disminuir el tráfico de red (algo como application/octet-stream ).

¿Cómo se puede lograr esto?

He intentado jugar con MultipartFormDataContent , pero parece que no puedo entender, cómo MultipartFormDataContent coincidirá con la firma del método del controlador.

Por ejemplo, reemplazando contenido a esto:

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();

lleva al error 415 ("Tipo de medio no compatible").


Convierto Byte Array en Base64 String para publicar:

await client.PostAsJsonAsync( apiUrl, new { message = "", content = Convert.ToBase64String(yourByteArray), } );

y el receptor puede convertir la byte array nuevo a la Base64 string mediante:

string base64Str = (string)postBody.data; byte[] fileBytes = Convert.FromBase64String(base64Str);


Fyi, para la serialización de protobuf para solicitar publicaciones de cuerpo.

LoginRequest loginRequest = new LoginRequest() { Code = "UserId", Password = "myPass", CMToken = "eIFt4lYTKGU:APA91bFZPe3XCDL2r1JUJuEQLlN3FoeFw9ULpw8ljEavNdo9Lc_-Qua4w9pTqdOFLTb92Kf03vyWBqkcvbBfYEno4NQIvp21kN9sldDt40eUOdy0NgMRXf2Asjp6FhOD1Kmubx1Hq7pc", }; byte[] rawBytes = ProtoBufSerializer.ProtoSerialize<LoginRequest>(loginRequest); var client = new HttpClient(); client.BaseAddress = new Uri("http://localhost:9000/"); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/x-protobuf")); //var bSonData = HttpExtensions.SerializeBson<T>(data); var byteArrayContent = new ByteArrayContent(rawBytes); byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-protobuf"); var result = client.PostAsync("Api/Login", byteArrayContent).Result; Console.WriteLine(result.IsSuccessStatusCode);


He creado este método genérico y multiplataforma para admitir el formato BSON utilizando la biblioteca Json.NET para que podamos reutilizarlo más tarde. Funciona bien en la plataforma Xamarin también.

public static async HttpResponseMessage PostBsonAsync<T>(string url, T data) { using (var client = new HttpClient()) { //Specifiy ''Accept'' header As BSON: to ask server to return data as BSON format client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/bson")); //Specify ''Content-Type'' header: to tell server which format of the data will be posted //Post data will be as Bson format var bSonData = HttpExtensions.SerializeBson<T>(data); var byteArrayContent = new ByteArrayContent(bSonData); byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("application/bson"); var response = await client.PostAsync(url, byteArrayContent); response.EnsureSuccessStatusCode(); return response; } }

El método para ayudar a serializar datos a formato BSON:

public static byte[] SerializeBson<T>(T obj) { using (MemoryStream ms = new MemoryStream()) { using (BsonWriter writer = new BsonWriter(ms)) { JsonSerializer serializer = new JsonSerializer(); serializer.Serialize(writer, obj); } return ms.ToArray(); } }

Luego puedes usar el método Post de esta manera:

var response = await PostBsonAsync<SamplePostRequest>("api/SomeData/Incoming", requestData);


WebAPI v2.1 y versiones posteriores admite BSON (Binary JSON) fuera de la caja , e incluso tiene incluido un MediaTypeFormatter para ello. Esto significa que puedes publicar todo tu mensaje en formato binario.

Si desea usarlo, deberá configurarlo en WebApiConfig :

public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Formatters.Add(new BsonMediaTypeFormatter()); } }

Ahora, puede utilizar el mismo BsonMediaTypeFormatter en el lado del cliente para serializar su solicitud:

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(); }

O bien, puede usar Json.NET para serializar su clase a BSON. Luego, especifique que desea usar "application / bson" como su "Tipo de contenido":

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(); } }