POST JsonObject với httpClient từ API Web


288

Tôi đang cố gắng POST JsonObjectbằng cách sử dụng HttpClientAPI Web. Tôi không chắc chắn làm thế nào để đi về điều này và không thể tìm thấy nhiều trong cách mã mẫu.

Đây là những gì tôi có cho đến nay:

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

Tôi nghĩ rằng tôi cần phải đóng vai JsonObjecttrò của mình StreamContentnhưng tôi đang gác máy ở bước đó.

Câu trả lời:


440

Với phiên bản mới HttpClientvà không có WebApigói, nó sẽ là:

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

Hoặc nếu bạn muốn nó async:

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

3
Trình xây dựng StringContent quá tải đó đã lừa tôi.
Thuyền trưởng Kenpachi

23
Hãy suy nghĩ kỹ trước khi gọi Kết quả theo phương pháp Async mặc dù blog.stephencleary.com/2012/07/dont-block-on-async-code.html
Ruchira

2
Đối với bất kỳ ai bị cám dỗ ném cái này usinggiống như tôi là: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty

Tôi đặt một usingxung quanh StringContentsáng tạo mặc dù.
bcr

Sử dụng câu trả lời này, tôi liên tục nhận được phản hồi "400 Yêu cầu Không hợp lệ" từ API Tôi đã gửi yêu cầu JSON của mình tới (Visual Studio 2017, .NET 4.6.2). Ngoài ra var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json")tôi phải đặt content.Headers.ContentType = new MediaTypeHeaderValue("application/json");. Xem câu trả lời dưới đây để biết thêm chi tiết.
anthls

161

Cách dễ nhất là sử dụng một StringContent, với biểu diễn JSON của đối tượng JSON của bạn.

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

14
Hãy lưu ý về loại nội dung. Tôi bỏ nó ra và để tôi gỡ lỗi lâu hơn tôi muốn.
Zapnologica

Bạn không nên vứt bỏ cá thể StringContent chứ?
Phil Haselden

63

Tùy thuộc vào phiên bản .NET của bạn, bạn cũng có thể sử dụng HttpClientExtensions.PostAsJsonAsyncphương thức.

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


4
Hiện được tìm thấy trong Microsoft.AspNet.Client.WebApi nuget
jle

2
Tôi vừa cài đặt nó từ Microsoft.AspNet.WebApi.Client
Adriaan Davel

Điều này đã giải quyết vấn đề của tôi. Tôi đã loay hoay một lúc (trong một thời gian dài) khi chuyển một lớp C # có chứa một số thuộc tính là Danh sách sử dụng client.PostAsync, client.SendAsync .. Tôi đã nhận được kết quả rất hỗn tạp. Nếu mảng trống, giải pháp API của tôi sẽ chọn nó, nhưng nếu mảng có một mục thì phương thức điều khiển không thể mô hình hóa liên kết JSON. Cảm ơn vì điều này .. Dường như với tôi rằng PostAsJsonAsync đáng tin cậy hơn khi chuyển đổi một đối tượng C # phức tạp thành JSON.
Franklin Tarter

Có một gói nuget cho điều này? Tôi ghét nó khi tôi chuyển dự án sang một máy mới và tài liệu tham khảo này luôn bị thiếu.
Zapnologica

Tìm kiếm cái này hay cái gì khác? nuget.org/packages/Microsoft.AspNet.WebApi.Client
user3285954

51

Nếu sử dụng 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");
}

Thí dụ:

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

đây không phải là lõi cụ thể của asp.net, nó thực sự chung chung xuống còn
4,5,6

JsonConvert.SerializeObjectcác vấn đề khi sử dụng DateTimes ISO 8601 Loại: Địa phương hoặc UTC ... hackered.co.uk/articles/ triệt
Kiquenet

21

Tôi không có đủ danh tiếng để thêm nhận xét về câu trả lời từ pomber vì vậy tôi sẽ đăng một câu trả lời khác. Sử dụng phương pháp tiếp cận của pomber, tôi liên tục nhận được phản hồi "400 Yêu cầu xấu" từ API Tôi đã gửi yêu cầu JSON của mình tới (Visual Studio 2017, .NET 4.6.2). Cuối cùng, sự cố đã được truy tìm đến tiêu đề "Kiểu nội dung" do StringContent () tạo ra không chính xác (xem https://github.com/dotnet/corefx/issues/7864 ).

tl; dr

Sử dụng câu trả lời của pomber với một dòng bổ sung để đặt chính xác tiêu đề theo yêu cầu:

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

Cảm ơn bạn, anthls. var content = new StringContent (jsonObject.ToString (), Encoding.UTF8, "application / json") là không đủ. Nó cần nội dung.Headers.ContentType = new MediaTypeHeaderValue ("application / json"); Cảm ơn bạn đã tiết kiệm sự tỉnh táo của tôi.
Gail Foad

1
Điều này đã làm việc tuyệt vời. Bất kỳ lý do tại sao "application / json" cần được đặt hai lần, một trong hàm tạo và một lần qua thuộc tính? Có phải là một lỗi?
Festus Martingale

@FestusMartingale: câu hỏi hay! Từ việc tôi đọc vấn đề github (được liên kết trong câu trả lời), việc chuyển qua "application/json"trong hàm StringContenttạo có thể không được yêu cầu vì nó được đặt rõ ràng trên thuộc tính kết quả content.Headers.ContentType. Tuy nhiên, tôi đã không kiểm tra điều này trong mã.
anthls

Có vẻ như máy chủ không hỗ trợ chuỗi loại nội dung đầy đủ. Khi bạn sử dụng hàm tạo mà không ghi đè ContentType, nó sẽ đặt giá trị là application/json; charset=utf-8.
Bertm13 ngày

2

mã trên nó trong 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)

Hy vọng điều này giúp đỡ

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.