web-dev-qa-db-fra.com

Comment passer un objet à HttpClient.PostAsync et le sérialiser en tant que corps JSON?

J'utilise System.Net.Http, j'ai trouvé plusieurs exemples sur le Web. J'ai réussi à créer ce code pour faire une requête POST:

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

tout fonctionne bien. Mais supposons que je veuille passer un troisième paramètre à la méthode POST, un paramètre appelé data. Le paramètre data est un objet comme celui-ci:

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

comment puis-je faire cela sans créer la KeyValuePair? Mon php RestAPI attend une entrée JSON, donc le FormUrlEncodedContent devrait envoyer le raw json correctement. Mais comment puis-je faire cela avec Microsoft.Net.Http? Merci.

66
IlDrugo

La réponse directe à votre question est la suivante: Non. La signature de la méthode PostAsync est la suivante:

public Task PostAsync (Uri requestUri, contenu HttpContent)

Ainsi, bien que vous puissiez passer un object à PostAsync, il doit être de type HttpContent et votre type anonyme ne répond pas à ce critère.

Cependant, il existe des moyens d'accomplir ce que vous voulez accomplir. Tout d'abord, vous devrez sérialiser votre type anonyme en JSON, l'outil le plus courant pour cela est Json.NET . Et le code pour cela est assez trivial:

var myContent = JsonConvert.SerializeObject(data);

Ensuite, vous devrez créer un objet de contenu pour envoyer ces données. J'utiliserai un objet ByteArrayContent, mais vous pourrez utiliser ou créer un type différent si vous le souhaitez.

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

Ensuite, vous voulez définir le type de contenu pour que l'API sache qu'il s'agit de JSON.

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

Ensuite, vous pouvez envoyer votre demande très similaire à votre exemple précédent avec le contenu du formulaire:

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

Sur une note de côté, appeler la propriété .Result comme vous le faites ici peut avoir certains effets secondaires négatifs tels que le verrouillage total, vous voulez donc faire attention à cela.

113
CodingGorilla

Vous devez transmettre vos données dans le corps de la demande sous forme de chaîne brute plutôt que FormUrlEncodedContent. Une façon de le faire est de le sérialiser dans une chaîne JSON:

var json = JsonConvert.SerializeObject(data);

Maintenant, tout ce que vous avez à faire est de passer la chaîne à la méthode post.

var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json");

var client = new HttpClient();
var response = await client.PostAsync(uri, stringContent);
41
elolos

Une solution simple consiste à utiliser Microsoft ASP.NET Web API 2.2 Client de NuGet .

Ensuite, vous pouvez simplement faire ceci et il sérialisera l'objet en JSON et définira l'en-tête Content-Type sur 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);
25
trydis

Il existe désormais un moyen plus simple d'utiliser .NET Standard ou .NET Core:

var client = new HttpClient();
var response = await client.PostAsync(uri, myRequestObject, new JsonMediaTypeFormatter());

NOTE: Pour utiliser la classe JsonMediaTypeFormatter, vous devez installer le package Microsoft.AspNet.WebApi.Client NuGet, qui peut être installé directement ou via un autre tel que Microsoft.AspNetCore.App.

En utilisant cette signature de HttpClient.PostAsync, vous pouvez passer n'importe quel objet et le JsonMediaTypeFormatter se chargera automatiquement de la sérialisation, etc.

Avec la réponse, vous pouvez utiliser HttpContent.ReadAsAsync<T> pour désérialiser le contenu de la réponse selon le type que vous attendez:

var responseObject = await response.Content.ReadAsAsync<MyResponseType>();
11
Ken Lyon