简体   繁体   English

从 Web API 使用 HttpClient 发布 JsonObject

[英]POSTing JsonObject With HttpClient From Web API

I'm trying to POST a JsonObject using HttpClient from Web API.我正在尝试使用来自 Web API 的HttpClient发布JsonObject I'm not quite sure how to go about this and can't find much in the way of sample code.我不太确定如何 go 关于这个并且在示例代码的方式中找不到太多。

Here's what I have so far:这是我到目前为止所拥有的:

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("", ???);

I think I need to cast my JsonObject as a StreamContent but I'm getting hung up on that step.我想我需要将我的JsonObject转换为StreamContent ,但我已经挂断了这一步。

With the new version of HttpClient and without the WebApi package it would be:使用新版本的HttpClient并且没有WebApi package 它将是:

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

Or if you want it async :或者,如果您希望它async

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

The easiest way is to use a StringContent , with the JSON representation of your JSON object.最简单的方法是使用StringContent ,使用 JSON object 的 JSON 表示形式。

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

Depending on your .NET version you could also use HttpClientExtensions.PostAsJsonAsync method.根据您的 .NET 版本,您还可以使用HttpClientExtensions.PostAsJsonAsync方法。

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

If using Newtonsoft.Json:如果使用 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");
}

Example:例子:

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

I don't have enough reputation to add a comment on the answer from pomber so I'm posting another answer.我没有足够的声誉来对 pomber 的答案添加评论,所以我发布了另一个答案。 Using pomber's approach I kept receiving a "400 Bad Request" response from an API I was POSTing my JSON request to (Visual Studio 2017, .NET 4.6.2).使用 pomber 的方法,我不断收到来自 API 的“400 Bad Request”响应,我正在将我的 JSON 请求发布到(Visual Studio 2017,Z303CB0EF9EDB9082D61BBBE5825D972)。 Eventually the problem was traced to the "Content-Type" header produced by StringContent() being incorrect (see https://github.com/dotnet/corefx/issues/7864 ).最终问题被追溯到由 StringContent() 生成的“Content-Type”header 不正确(请参阅https://github.com/dotnet/corefx/issues/7864 )。

tl;dr tl;博士

Use pomber's answer with an extra line to correctly set the header on the request:使用 pomber 的答案和额外的一行来正确设置 header 请求:

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

the code over it in vbnet: 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)

Hope this help希望这有帮助

I spent hours trying to solve this.我花了几个小时试图解决这个问题。 But @anthls anwser saved my skin.但是@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);

Thank you pomber but for谢谢你,但是为了

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

I used我用了

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

because Result makes app lock for high request因为 Result 使应用程序锁定高请求

I want to answer all in one response when doing this job as a note for all and myself:在做这项工作时,我想一次性回答所有问题,作为对所有人和我自己的说明:

According to Serez's answer HttpContent derived classes list as below https://stackoverflow.com/a/42380027/914284根据 Serez 的回答 HttpContent 派生类列表如下https://stackoverflow.com/a/42380027/914284

HttpClient PostAsync has some background depending on the context you working on! HttpClient PostAsync 有一些背景,具体取决于您处理的上下文!

  • You can post data by the type that you want to send to server in cases Server context waits it as bellow在服务器上下文等待它的情况下,您可以按要发送到服务器的类型发布数据,如下所示
 [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)

When writing FromForm or Body it has working as FromForm.在编写 FromForm 或 Body 时,它作为 FromForm 工作。 FromBody needs json content otherwise it requires KeyValuePairs as rows. FromBody 需要 json 内容,否则它需要 KeyValuePairs 作为行。 There is some implementations for both of them such as below:它们都有一些实现,如下所示:

For FromForm : I have used an extension对于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 } };
        }
    }

For FromBody : Use any json converter library Newtonsoft or microsoft对于FromBody :使用任何 json 转换器库 Newtonsoft 或 microsoft

using Newtonsoft.Json;

var jsonString = JsonConvert.SerializeObject(obj);

In both of them, content type should be defined according the requirement, for example for json (Write to header)在这两个中,内容类型应根据要求定义,例如 json(写入标题)

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

or another usage或其他用法

        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
        }

If you should use authorization on the context also you can provide authorization as below:如果您应该在上下文中使用授权,您也可以提供如下授权:

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Your Oauth token");

I Faced same issue ie var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");我遇到了同样的问题,即 var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json"); gave "400 Bad Request" Serilizing jsonObject seperately and passing the string in StringContent() solved issue for me, no need to set Encoding.UTF8 seperately.给了“400 Bad Request” Serilizing jsonObject 并在 StringContent() 中传递字符串为我解决了问题,无需单独设置 Encoding.UTF8。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM