从Web API使用HttpClient发布JsonObject


288

我正在尝试JsonObject通过HttpClientWeb API发布。我不太确定该怎么做,在示例代码中找不到太多。

这是我到目前为止的内容:

var myObject = (dynamic)new JsonObject();
myObject.Data = "some data";
myObject.Data2 = "some more data";

HttpClient httpClient = new HttpClient("myurl");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

HttpResponseMessage response = httpClient.Post("", ???);

我想我需要把我JsonObject当成演员,StreamContent但是我对此很挂念。

Answers:


440

使用的新版本HttpClient和不使用的WebApi软件包,它将是:

var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
var result = client.PostAsync(url, content).Result;

或者,如果您想要的话async

var result = await client.PostAsync(url, content);

3
这个重载的StringContent构造函数为我完成了窍门。
肯帕奇船长


2
对于任何想像using这样扔掉它的人,我是:aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty

不过我还是using围绕着StringContent创作。
bcr

使用此答案,我不断收到来自我将JSON请求发布到(Visual Studio 2017,.NET 4.6.2)的API的“ 400错误请求”响应。除了var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json")我要设定content.Headers.ContentType = new MediaTypeHeaderValue("application/json");。有关更多详细信息,请参见下面的答案。
anthls

161

最简单的方法是使用StringContent带有JSON对象的JSON表示形式的。

httpClient.Post(
    "",
    new StringContent(
        myObject.ToString(),
        Encoding.UTF8,
        "application/json"));

14
注意内容类型。我忽略了它,让我调试的时间比我想要的长得多。
Zapnologica

但是,您是否应该不处理StringContent实例呢?
Phil Haselden

63

根据您的.NET版本,您也可以使用HttpClientExtensions.PostAsJsonAsync方法。

https://msdn.microsoft.com/zh-CN/library/system.net.http.httpclientextensions.postasjsonasync.aspx


4
现在在Microsoft.AspNet.Client.WebApi中找到nuget
jle,2016年

2
我刚刚从Microsoft.AspNet.WebApi.Client安装了它
Adriaan Davel

这解决了我的问题。我在传递一个C#类时花了很长时间(很长时间),该类包含一些使用client.PostAsync,client.SendAsync.s列出的属性。我得到的结果很复杂。如果数组为空,则我的API解决方案会选择它,但是如果数组中有一个项目,则控制器方法将无法对JSON进行模型绑定。谢谢。。在我看来,PostAsJsonAsync更可靠地将复杂的C#对象转换为JSON。
富兰克林·塔特

是否有一个nuget包?当我将项目转移到新机器上时,我讨厌它,并且始终缺少此参考。
Zapnologica


51

如果使用Newtonsoft.Json:

using Newtonsoft.Json;
using System.Net.Http;
using System.Text;

public static class Extensions
{
    public static StringContent AsJson(this object o)
        => new StringContent(JsonConvert.SerializeObject(o), Encoding.UTF8, "application/json");
}

例:

var httpClient = new HttpClient();
var url = "https://www.duolingo.com/2016-04-13/login?fields=";
var data = new { identifier = "username", password = "password" };
var result = await httpClient.PostAsync(url, data.AsJson())

这不是特定于asp.net的核心,其实际通用名称甚至降至4.5.6
danatcofo

JsonConvert.SerializeObject使用DateTimes ISO 8601类型的问题:本地或UTC ... hackered.co.uk/articles/…–
Kiquenet

21

我的信誉不足,无法在Pomber的答案中添加评论,所以我要发布另一个答案。使用Pomber的方法,我不断收到来自我将JSON请求发布到(Visual Studio 2017,.NET 4.6.2)的API的“ 400 Bad Request”响应。最终,问题被追溯到StringContent()产生的“ Content-Type”标头不正确(请参见https://github.com/dotnet/corefx/issues/7864)。

tl; dr

使用Pomber的答案和额外的一行以正确设置请求的标头:

var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var result = client.PostAsync(url, content).Result;

谢谢你,安瑟斯。var content = new StringContent(jsonObject.ToString(),Encoding.UTF8,“ application / json”)不够。它需要content.Headers.ContentType = new MediaTypeHeaderValue(“ application / json”); 谢谢您保存我的理智。
盖尔·佛阿德

1
这很棒。有什么理由需要两次设置“ application / json”,一次在构造函数中,一次通过属性设置?是虫子吗?
Festus Martingale

@FestusMartingale:好问题!从我的GitHub的问题(在答题链接)的通过阅读"application/json"StringContent构造函数可能并不需要,因为它被明确设置对所得到的content.Headers.ContentType财产。但是,我尚未在代码中对此进行测试。
anthls

看起来服务器不支持完整的内容类型字符串。在不覆盖ContentType的情况下使用构造函数时,它将值设置为application/json; charset=utf-8
Bertm13

2

在vbnet中的代码:

dim FeToSend as new (object--> define class)

Dim client As New HttpClient
Dim content = New StringContent(FeToSend.ToString(), Encoding.UTF8,"application/json")
content.Headers.ContentType = New MediaTypeHeaderValue( "application/json" )
Dim risp = client.PostAsync(Chiamata, content).Result

msgbox(risp.tostring)

希望有帮助

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.