使用HttpClient从Web API发布JsonObject

我试图从Web API使用HttpClient POST一个JsonObject。我不太确定如何做到这一点,也找不到很多样例代码。

以下是我目前所了解到的:

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,但我在这一步上被挂断了。

537938 次浏览

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

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

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

https://msdn.microsoft.com/en-us/library/system.net.http.httpclientextensions.postasjsonasync.aspx

有了新版本的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);

如果使用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())

我没有足够的声誉来评论pomber的答案,所以我发布了另一个答案。使用pomber的方法,我不断收到来自我正在发布JSON请求的API的“400个坏请求”响应(Visual Studio 2017, . net 4.6.2)。最终问题被追踪到StringContent()产生的“Content-Type”标头不正确(参见https://github.com/dotnet/corefx/issues/7864)。

博士tl;

使用pomber's answer和额外的一行来正确设置请求的头部:

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

上面的代码在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)

希望这对你有所帮助

谢谢你pomber

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

我使用

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

因为结果使应用程序锁定高请求

当我做这份工作时,我想用一个回答来回答所有问题,作为对所有人和我自己的提醒:

根据Serez的答案HttpContent派生类列表如下 https://stackoverflow.com/a/42380027/914284 < / p >

HttpClient PostAsync有一些背景,这取决于你正在工作的上下文!

  • 你可以根据你想要发送到服务器的类型来发布数据 服务器上下文等待
    [HttpPost]
public async Task<IActionResult> Submit(MyModel model)
[HttpPost]
public async Task<IActionResult> Submit([FromForm] MyModel model)
[HttpPost]
public async Task<IActionResult> Submit([FromBody] MyModel model)
当写入FromForm或Body时,它的工作方式是FromForm。 FromBody需要json内容,否则它需要KeyValuePairs作为行。它们都有一些实现,如下所示

对于FromForm:我已经使用了扩展

public static class HelperExtensions
{
public static FormUrlEncodedContent ToFormData(this object obj)
{
var formData = obj.ToKeyValue();


return new FormUrlEncodedContent(formData);
}


public static IDictionary<string, string> ToKeyValue(this object metaToken)
{
if (metaToken == null)
{
return null;
}


// Added by me: avoid cyclic references
var serializer = new JsonSerializer { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
if (metaToken is not JToken token)
{
// Modified by me: use serializer defined above
return ToKeyValue(JObject.FromObject(metaToken, serializer));
}


if (token.HasValues)
{
var contentData = new Dictionary<string, string>();
foreach (var child in token.Children().ToList())
{
var childContent = child.ToKeyValue();
if (childContent != null)
{
contentData = contentData.Concat(childContent)
.ToDictionary(k => k.Key, v => v.Value);
}
}


return contentData;
}


var jValue = token as JValue;
if (jValue?.Value == null)
{
return null;
}


var value = jValue?.Type == JTokenType.Date ?
jValue?.ToString("o", CultureInfo.InvariantCulture) :
jValue?.ToString(CultureInfo.InvariantCulture);


return new Dictionary<string, string> { { token.Path, value } };
}
}

对于FromBody:使用任何json转换器库Newtonsoft或microsoft

using Newtonsoft.Json;


var jsonString = JsonConvert.SerializeObject(obj);

在这两种类型中,内容类型都应该根据需求来定义,例如json(写入头)

request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

或者另一种用法

        using (var content = new StringContent(JsonConvert.SerializeObject(answer), System.Text.Encoding.UTF8, "application/json"))
{
var answerResponse = await client.PostAsync(url, content);
//use await it has moved in some context on .core 6.0
}

如果你应该在上下文上使用授权,你也可以提供如下授权:

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Your Oauth token");
我花了几个小时来解决这个问题。 但是@anthls anwser救了我的命
var data = new StringContent(JsonConvert.SerializeObject(new
{
abc = "jsjs",
xyz = "hhhh"
}));
data.Headers.ContentType = new MediaTypeHeaderValue("application/json"); // <--
var response = await client.PostAsync(url, data);

我也遇到过同样的问题

var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");

给了

“400个坏请求”;

单独序列化JsonObject并在StringContent()中传递字符串为我解决了问题,不需要单独设置Encoding.UTF8