2016-04-14 10 views
22

Sto usando System.Net.Http, ho trovato diversi esempi sul web. Sono riuscito a creare questo codice per effettuare una richiesta di POST:Come passare un oggetto a HttpClient.PostAsync e serializzare come corpo JSON?

public static string POST(string resource, string token) 
{ 
    using (var client = new HttpClient()) 
    { 
     client.BaseAddress = new Uri(baseUri); 
     client.DefaultRequestHeaders.Add("token", token); 

     var content = new FormUrlEncodedContent(new[] 
     { 
      new KeyValuePair<string, string>("", "") 
     }); 

     var result = client.PostAsync("", content).Result; 
     string resultContent = result.Content.ReadAsStringAsync().Result; 
     return resultContent; 
    } 
} 

tutti lavorando bene. Ma supponiamo di voler passare un terzo parametro al metodo POST, un parametro chiamato data. Il param dati è un oggetto come questo:

object data = new 
{ 
    name = "Foo", 
    category = "article" 
}; 

come posso farlo senza creare il KeyValuePair? Il mio php RestAPI attende un input JSON, quindi lo FormUrlEncodedContent dovrebbe inviare correttamente il json raw. Ma come posso fare questo con Microsoft.Net.Http? Grazie.

+0

Se ho capito la tua domanda, si desidera inviare il contenuto JSON invece di forma codificata contenuti giusto (e per estensione vuoi che il tuo tipo anonimo sia serializzato come JSON in quel contenuto)? – CodingGorilla

+0

@CodingGorilla yes è un tipo anonimo. – IlDrugo

risposta

39

La risposta dritto fino alla tua domanda è: No. La firma per il metodo PostAsync è il seguente:

pubblica Task PostAsync (Uri requestUri, HttpContent contenuti)

Così, mentre è possibile passare un object a PostAsync deve essere di tipo HttpContent e il tipo anonimo non soddisfa tali criteri.

Tuttavia, ci sono modi per realizzare ciò che si desidera realizzare. Innanzitutto, è necessario serializzare il tipo anonimo su JSON, lo strumento più comune è Json.NET. E il codice per questo è abbastanza banale:

var myContent = JsonConvert.SerializeObject(data); 

Successivamente, sarà necessario costruire un oggetto di contenuti per inviare questi dati, userò un oggetto ByteArrayContent, ma si potrebbe utilizzare o creare un tipo diverso se si voleva .

var buffer = System.Text.Encoding.UTF8.GetBytes(myContent); 
var byteContent = new ByteArrayContent(buffer); 

Successivamente, si desidera impostare il tipo di contenuto per consentire all'API di sapere che questo è JSON.

byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 

Quindi è possibile inviare la richiesta di molto simile al tuo esempio precedente con il contenuto del modulo:

var result = client.PostAsync("", byteContent).Result 

Su un lato nota, chiamando la proprietà .Result come si sta facendo qui può avere un po 'bad side effects come dead lock, quindi vuoi stare attento con questo.

+0

Ok, è molto chiaro. Grazie per questa risposta. Solo una domanda: quando viene eseguito un 'POST, PUT, DELETE', di solito l'API restituisce' TRUE', ho dichiarato il metodo come 'stringa', ma quando lo faccio:' restituisce risultato; 'Ottengo:' Can not Converti HttpResponseMessage in string', dovrei cambiare la dichiarazione del metodo? Ho bisogno della risposta stringa perché dovrò deserializzare dopo in un altro metodo di classe. – IlDrugo

+1

Se è necessario deserializzare il corpo della risposta, quindi restituire la stringa come nella domanda (usando 'result.Content.ReadAsStringAsync()') probabilmente sta bene. A seconda della struttura dell'applicazione, potrebbe essere preferibile restituire direttamente l'oggetto 'Contenuto' se è necessario esaminare le intestazioni per determinare quale sia il tipo conent (ad esempio XML o JSON). Ma se ** conosci **, restituirà sempre JSON (o qualche altro formato), quindi restituirà il corpo della risposta come una stringa dovrebbe essere ok. – CodingGorilla

+0

Capito, grazie :) – IlDrugo

6

È necessario passare i dati nel corpo della richiesta come stringa non elaborata anziché FormUrlEncodedContent. Un modo per farlo è quello di serializzare in una stringa JSON:

var json = JsonConvert.SerializeObject(data); 

Ora tutto quello che dovete fare è passare la stringa al metodo post.

var stringContent = new HttpStringContent(json, 
         UnicodeEncoding.Utf8, 
         "application/json"); 

var client = new HttpClient(); 
var response = await client.PostAsync(uri, stringContent); 
+2

Si noti che 'HttpStringContent' è una classe di runtime di Windows che potrebbe non essere sempre disponibile. Vedere la sezione Requisiti [qui] (https://msdn.microsoft.com/en-us/library/windows/apps/windows.web.http.httpstringcontent.aspx). – CodingGorilla

+0

Sì, perché è una libreria di classi portatile. – IlDrugo

4

Una soluzione semplice è quella di utilizzare Microsoft ASP.NET Web API 2.2 Client da NuGet.

Poi si può semplicemente fare questo e sarà serializzare l'oggetto JSON e impostare l'intestazione Content-Type a application/json; charset=utf-8:

var data = new 
{ 
    name = "Foo", 
    category = "article" 
}; 

var client = new HttpClient(); 
client.BaseAddress = new Uri(baseUri); 
client.DefaultRequestHeaders.Add("token", token); 
var response = await client.PostAsJsonAsync("", data); 
Problemi correlati