2015-08-24 21 views
20

Ben Web API sunucuya bu verileri yayınlamak istediğiniz HttpClient kullanarak Web API sunucusuna diziMesaj bayt

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

ve bu - istemci için:

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

her şey yolunda çalışıyor (en azından, hata ayıklayıcısında PostIncomingData durduruyor).

byte dizisi olduğundan, JSON olarak serileştirmek istemiyorum ve ağ trafiğini azaltmak için (application/octet-stream gibi bir şey) ikili veri olarak göndermek istiyorum. Bu sağlanabilir nasıl

?

MultipartFormDataContent ile oynamayı denedim, ancak anlayamadığım gibi görünüyor, denetçinin yönteminin imzası eşleşmeyecek şekilde nasıl MultipartFormDataContent. Bu içerik yerine

Ör:

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

("Desteklenmeyen ortam türü") 415 hata yol açar. Hatta

cevap

22

WebAPI v2.1 ve supports BSON (Binary JSON) out of the box ötesinde ve MediaTypeFormatter bunun için dahil bulunmaktadır. Bu, mesajınızın tamamını ikili biçimde gönderebileceğiniz anlamına gelir. Bunu kullanmak istiyorsanız

, sen WebApiConfig bunu ayarlamak gerekir:

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

Şimdi, şu an kullanım aynı BsonMediaTypeFormatter istemci tarafında isteğinizi seri hale getirmek için:

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

Veya, BSON için sınıf seri hale getirmek için Json.NET kullanabilirsiniz. Ben bu yüzden can Json.NET kitaplığını kullanarak BSON biçimini desteklemek için bu jenerik ve çapraz platform yöntemi oluşturduk

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

Teşekkürler, çalışır kusursuzca. Aslında sağladığınız bağlantı, istemci tarafı için daha basit bir örnek içeriyor. – Dennis

+0

Bu seri için 'BsonMediaTypeFormatter' kullanır @Dennis. Sanırım her iki şekilde de alabilirsin. Cevabım için başka bir örnek ekleyeceğim. –

+1

İkinci kod örneğiniz eksik içerik türü: 'var byteArrayContent = new ByteArrayContent (stream.ToArray()); byteArrayContent.Headers.ContentType = yeni MediaTypeHeaderValue ("application/bson"); var result = client.PostAsync bekliyor ( "api/someData/Giden", byteArrayContent); PostBson için ' –

2

: Daha sonra, "Content-Type" olarak "application/BSON" kullanmak istiyorum belirtmek Daha sonra tekrar kullanabilirsiniz. Xamarin platformunda da iyi çalışıyor. vücudu istemek için protobuf serileştirme için,

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

dönüş tipi Görev Görev olmalıdır yoksa ben sadece bu kodu doğru güncellenir @JuanZamora boşluk –

+1

anahtar kelimeyi bekliyor –

0

Bilginize:

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

Sonra böyle Mesaj yöntemi kullanabilirsiniz:

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

yöntem BSON biçimine veri tefrika yardım etmek gönderiler

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