मैं HttpClient.PostAsync को ऑब्जेक्ट कैसे पास करूं और JSON बॉडी के रूप में अनुक्रमित करूं?


93

मैं उपयोग कर रहा हूं System.Net.Http, मुझे वेब पर कई उदाहरण मिले। मैंने 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;
    }
 }

सभी ठीक काम कर रहे हैं। लेकिन मान लीजिए कि मैं POSTविधि के लिए एक तीसरा परम पास चाहता हूं , जिसे एक परम कहा जाता है data। डेटा परम इस तरह से एक वस्तु है:

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

मैं कैसे कर सकता हूँ कि बनाने के बिना KeyValuePair? मेरी php RestAPIएक json इनपुट की प्रतीक्षा करती है, इसलिए सही ढंग FormUrlEncodedContentसे rawjson को भेजना चाहिए । लेकिन मैं इसके साथ कैसे कर सकता हूं Microsoft.Net.Http? धन्यवाद।


यदि मैं आपके प्रश्न को समझता हूं, तो आप फॉर्म एन्कोडेड सामग्री के बजाय JSON सामग्री भेजना चाहते हैं (और विस्तार से आप अपने अनाम प्रकार को उस सामग्री में JSON के रूप में क्रमबद्ध किया जाना चाहते हैं)?
कोडिंगगोरिल्ला

@CodingGorilla हाँ एक अनाम प्रकार है।
इलद्रूगो

3
भविष्य के पाठकों के लिए एक साइड नोट के रूप में, इसके usingलिए उपयोग न करें HttpClientaspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
मैक्सशूट

2
Microsoft से नोट क्यों usingनहीं किया जाना चाहिए: HttpClient is intended to be instantiated once and reused throughout the life of an application. The following conditions can result in SocketException errors: Creating a new HttpClient instance per request. Server under heavy load. Creating a new HttpClient instance per request can exhaust the available sockets. docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/…
Ogglas

जवाबों:


155

आपके प्रश्न का सीधा उत्तर है: नहीं। PostAsyncविधि का हस्ताक्षर इस प्रकार है:

सार्वजनिक टास्क पोस्टएन्स्प्स (उरी अनुरोध, HttpContent कंटेंट)

तो, आप पास कर सकते हैं, जबकि एक objectके लिए PostAsyncयह प्रकार का होना चाहिए HttpContentऔर अपने गुमनाम प्रकार है कि मानदंडों को पूरा नहीं करता है।

हालाँकि, आप जो पूरा करना चाहते हैं उसे पूरा करने के तरीके हैं। सबसे पहले, आपको अपने अनाम प्रकार को JSON पर क्रमांकित करना होगा , इसके लिए सबसे सामान्य उपकरण Json.NET है । और इस कोड के लिए बहुत तुच्छ है:

var myContent = JsonConvert.SerializeObject(data);

इसके बाद, आपको इस डेटा को भेजने के लिए एक कंटेंट ऑब्जेक्ट का निर्माण करना होगा, मैं किसी ByteArrayContentऑब्जेक्ट का उपयोग करूंगा , लेकिन यदि आप चाहते हैं तो आप एक अलग प्रकार का उपयोग या निर्माण कर सकते हैं।

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

इसके बाद, आप एपीआई टाइप करने के लिए सामग्री प्रकार सेट करना चाहते हैं यह JSON है।

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

तब आप अपने पिछले उदाहरण को फॉर्म सामग्री के साथ अपने अनुरोध के समान भेज सकते हैं:

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

एक साइड नोट पर, .Resultजैसे आप यहां संपत्ति कर रहे हैं , कॉल करने से डेड लॉकिंग जैसे कुछ बुरे दुष्प्रभाव हो सकते हैं , इसलिए आप इससे सावधान रहना चाहते हैं।


ठीक है यह बहुत स्पष्ट है। इस उत्तर के लिए धन्यवाद। बस एक सवाल: जब एक POST, PUT, DELETEप्रदर्शन किया जाता है, तो आमतौर पर एपीआई वापस आ जाता है TRUE, मैंने विधि की घोषणा की string, लेकिन जब मैं करता return result;हूं : मुझे मिलता है: Can't Convert HttpResponseMessage in stringक्या मुझे विधि की घोषणा को बदलना चाहिए? मुझे स्ट्रिंग प्रतिक्रिया की आवश्यकता है क्योंकि मुझे अन्य वर्ग विधि के बाद इसे डिसेर्बलाइज करना होगा।
इलद्रुगो

2
यदि आपको प्रतिक्रिया के शरीर को विचलित करने की आवश्यकता है, तो आपके प्रश्न में (जिस तरह से) आपके पास स्ट्रिंग वापस लौटना result.Content.ReadAsStringAsync()संभवत: ठीक है। आपके एप्लिकेशन संरचना के आधार पर, Contentऑब्जेक्ट को सीधे वापस करने के लिए बेहतर हो सकता है यदि आपको यह निर्धारित करने के लिए हेडर का निरीक्षण करने की आवश्यकता है कि शंकु प्रकार क्या है (जैसे XML या JSON)। लेकिन अगर आप जानते हैं कि यह हमेशा JSON (या कुछ अन्य प्रारूप) को वापस करने जा रहा है तो बस एक स्ट्रिंग के रूप में प्रतिक्रिया बॉडी को वापस करना चाहिए।
कोडिंगगोरिला

पूछने के लिए क्षमा करें, लेकिन यदि डेटा प्रकार का है, तो क्या आपको ऐसा करने की आवश्यकता है StringContent?
MyDaftQuestions

1
@MyDaftQuestions मुझे बिल्कुल यकीन नहीं है कि आप क्या पूछ रहे हैं, लेकिन जब आप इसे प्राप्त करते हैं तो आप StringContentसीधे पास कर सकते हैं । PostAsyncHttpContent
कोडिंगगोरिल्ला

@CodingGorilla, कि था कि मैं क्या पूछ रहा था। धन्यवाद :)
MyDaftQuestions

67

आपको अनुरोधित निकाय में अपना डेटा पास करने की आवश्यकता है बजाय एक कच्चे स्ट्रिंग के FormUrlEncodedContent। ऐसा करने का एक तरीका इसे JSON स्ट्रिंग में क्रमबद्ध करना है:

var json = JsonConvert.SerializeObject(data); // or JsonSerializer.Serialize if using System.Text.Json

अब आपको केवल स्ट्रिंग को पोस्ट विधि में पास करना होगा।

var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); // use MediaTypeNames.Application.Json in Core 3.0+ and Standard 2.1+

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

क्या है stringContent? मेरे मामले में stringContentमान है "\"\""। क्या यह सही मूल्य है?
R15

क्या आपके c # कोड से vb में स्ट्रिंग रिजल्ट प्राप्त करना संभव है? मुझे पता चला कि यह काफी समान है ....
गमरुह

42

एक सरल समाधान NuGetMicrosoft ASP.NET Web API 2.2 Client से उपयोग करना है ।

तो आप बस यह कर सकते हैं और यह JSON के ऑब्जेक्ट को क्रमबद्ध करेगा और Content-Typeहेडर को 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);

2
निश्चित रूप से PostAsJsonAsync का उपयोग करना है
कैट लिम Ruiz

25

अब के साथ एक सरल तरीका है .NET Standardया .NET Core:

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

नोट:JsonMediaTypeFormatter कक्षा का उपयोग करने के लिए , आपको Microsoft.AspNet.WebApi.ClientNuGet पैकेज को स्थापित करने की आवश्यकता होगी , जिसे सीधे स्थापित किया जा सकता है, या जैसे अन्य के माध्यम से Microsoft.AspNetCore.App

के इस हस्ताक्षर का उपयोग करके HttpClient.PostAsync, आप किसी भी वस्तु में पास कर सकते हैं और JsonMediaTypeFormatterवसीयतनामा स्वचालित रूप से क्रमांकन आदि का ध्यान रखेंगे।

प्रतिक्रिया के साथ, आप HttpContent.ReadAsAsync<T>उस प्रतिक्रिया सामग्री का वर्णन करने के लिए उपयोग कर सकते हैं जिस प्रकार की आप अपेक्षा कर रहे हैं:

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

1
यह किस संस्करण का उपयोग कर रहा है? मेरा संस्करण System.Net.ttp नामस्थान में "फ़ॉर्मेटिंग" नहीं पा सकता
TemporaryFix

1
जैसा कि मैंने उल्लेख किया है @Programmatic का उपयोग करना चाहिए .NET Standardया .NET Core। शायद आप उपयोग कर रहे हैं .NET Framework? मेरे प्रोजेक्ट में, JsonMediaTypeFormatter को यहाँ से लोड किया जा रहा है: C: \ Program Files \ dotnet \ sdk \ NuGetFallbackFolder \ microsoft.aspnet.webapi.client / 5.2.6 \ lib \ netstandard2.0 \ System.Net.Http.Formatting। dll
केन ल्योन

1
यदि आप पहले से ही उन प्रोजेक्ट प्रकारों में से एक का उपयोग कर रहे हैं, तो हो सकता है कि आपको एक अतिरिक्त NuGet पैकेज जोड़ने की आवश्यकता हो। मैं वास्तव में भूल जाता हूं जो मेरे लिए स्वचालित रूप से शामिल थे। मेरे मामले में, इसे Microsoft.AspNetCore.App NuGet पैकेज के भाग के रूप में शामिल किया गया था।
केन ल्योन

1
मैं .NET कोर का उपयोग कर रहा था, लेकिन मुझे नहीं लगता कि मेरा समाधान c # भाषा के नवीनतम संस्करण का उपयोग करने के लिए सेट किया गया था। मैंने अपडेट किया और यह काम कर गया। धन्यवाद
TemporaryFix

1
@Programmatic आपका स्वागत है। मुझे खुशी है कि आप इसे काम कर रहे हैं! मैंने NuGet पैकेज के बारे में अपने उत्तर में एक नोट जोड़ा है।
केन ल्योन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.