आप HttpClient अनुरोध के लिए सामग्री-प्रकार शीर्षलेख कैसे सेट करते हैं?


739

मैं एक एपीआई द्वारा आवश्यक वस्तु के Content-Typeहेडर को सेट करने की कोशिश कर HttpClientरहा हूं जिसे मैं कॉल कर रहा हूं।

मैंने Content-Typeनीचे जैसा सेट करने की कोशिश की :

using (var httpClient = new HttpClient())
{
    httpClient.BaseAddress = new Uri("http://example.com/");
    httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
    httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json");
    // ...
}

यह मुझे Acceptशीर्षलेख जोड़ने की अनुमति देता है, लेकिन जब मैं Content-Typeइसे जोड़ने की कोशिश करता हूं तो निम्न अपवाद फेंकता है:

गलत शीर्षक वाला नाम। सुनिश्चित करें कि अनुरोध हेडर का उपयोग वस्तुओं के HttpRequestMessageसाथ प्रतिक्रिया हेडर HttpResponseMessage, और सामग्री हेडर के साथ किया जाता HttpContentहै।

मैं Content-Typeएक HttpClientअनुरोध में शीर्ष लेख कैसे सेट कर सकता हूं ?


आप अनुसरण कर सकते हैं कि .NET कोर में HttpWebRequest यह कैसे करता है (यह आंतरिक रूप से HttpClient का उपयोग करता है), github.com/dotnet/corefx/blob/master/src/System.Net.Requestests देखें
jiping-s

जवाबों:


928

सामग्री प्रकार सामग्री का हेडर है, अनुरोध का नहीं, यही कारण है कि यह विफल हो रहा है। AddWithoutValidationजैसा कि रॉबर्ट लेवी ने सुझाव दिया है, काम कर सकता है, लेकिन आप अनुरोध सामग्री बनाते समय सामग्री प्रकार भी सेट कर सकते हैं (ध्यान दें कि कोड स्निपेट दो स्थानों के लिए "एप्लिकेशन / जोंस" जोड़ता है-स्वीकार और सामग्री-प्रकार हेडर के लिए):

HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://example.com/");
client.DefaultRequestHeaders
      .Accept
      .Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header

HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "relativeAddress");
request.Content = new StringContent("{\"name\":\"John Doe\",\"age\":33}",
                                    Encoding.UTF8, 
                                    "application/json");//CONTENT-TYPE header

client.SendAsync(request)
      .ContinueWith(responseTask =>
      {
          Console.WriteLine("Response: {0}", responseTask.Result);
      });

32
वैकल्पिक रूप से, Response.Content.Headersअधिकांश समय काम करेगा।
जॉन गित्जन

4
@AshishJain एसओ के अधिकांश जवाब मैंने एएसपीनेट Response.Content.Headersवेब एपीआई के लिए शामिल किए हैं, या तो काम नहीं किया है, लेकिन HttpContext.Current.Response.ContentTypeयदि आपको ज़रूरत है तो आप इसे आसानी से सेट कर सकते हैं ।
jerhewet

6
@jerhewet मैंने निम्नलिखित तरीके से उपयोग किया जो मेरे लिए काम करता है। var सामग्री = नया StringContent (डेटा, एनकोडिंग.UTF8, "एप्लिकेशन / जसन");
आशीष-बेजोवियल

22
सामग्री-प्रकार पेलोड के साथ एक HTTP संदेश की एक संपत्ति है; इसका अनुरोध बनाम प्रतिक्रिया से कोई लेना-देना नहीं है।
जूलियन रेज़के ने

6
दिलचस्प। मैंने तीन मानकों के साथ एक नया स्ट्रिंगरेंट बनाने की कोशिश की और यह काम नहीं किया। मैं तब मैन्युअल रूप से: request.Content.Headers.Remove ("सामग्री-प्रकार") और फिर: request.Content.Headers.Add ("सामग्री-प्रकार", "आवेदन / क्वेरी + json") और यह काम किया। अजीब।
बिल नोएल

163

जो लोग जॉन्स को कार्लो समाधान के लिए टिप्पणी नहीं करते थे, उनके लिए ...

req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

इसने पीडीऍफ़ डाउनलोड करने में अंतर किया। फोन से इसने एक HTML डाउनलोड करने की कोशिश की। एक्सटेंशन को परिवर्तित करने के बाद फ़ाइल सामान्य रूप से एन्कोडेड थी।
मैट्टो डिफैंटी

मुझे अंत में .TString () को फेंकना पड़ा, लेकिन हाँ इसने WCF सेवा कार्यान्वयन के लिए काम किया।
जॉन मेयर

2
मैं अंततः यह पता लगाऊंगा कि परीक्षण और त्रुटि के द्वारा "ऑब्जेक्ट" किस प्रकार का है ... ...... लेकिन यह दिखाने के लिए बहुत अच्छा होगा। आपके विचार करने के लिए धन्यवाद।
ग्रेनाकोडर

4
बस इतना ही लोग जानते हैं, MediaTypeHeaderValue का उपयोग कर एक त्रुटि वापस करेगा यदि चार्ट सेट करने का प्रयास किया जाता है, जैसे; response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/xml; charset=utf-8");
एमबीक

3
कार्लो के समाधान के लिए जॉन्स ने टिप्पणी की। Response.Content.Headers, लेकिन आप req.Content.Headers का उपयोग कर रहे हैं? अर्थात अनुरोध बनाम प्रतिक्रिया?
joedotnot

52

यदि आप एक छोटे पुस्तकालय पर निर्भर नहीं हैं, Flurl.Http [प्रकटीकरण: मैं लेखक हूँ] यह इस सरल बनाता है। इसकी PostJsonAsyncविधि सामग्री को क्रमबद्ध करने और content-typeहेडर सेट करने दोनों का ध्यान रखती है , और ReceiveJsonप्रतिक्रिया को निष्क्रिय करती है। यदि acceptशीर्ष लेख आवश्यक है तो आपको स्वयं को सेट करना होगा, लेकिन फ़्लर्ल ऐसा करने के लिए एक बहुत ही अच्छा तरीका प्रदान करता है:

using Flurl.Http;

var result = await "http://example.com/"
    .WithHeader("Accept", "application/json")
    .PostJsonAsync(new { ... })
    .ReceiveJson<TResult>();

Flurl हुड के तहत HttpClient और Json.NET का उपयोग करता है, और यह एक PCL है इसलिए यह विभिन्न प्लेटफार्मों पर काम करेगा।

PM> Install-Package Flurl.Http

यदि सामग्री एप्लिकेशन / x-www-form-urlencoded है तो कैसे भेजें?
व्लादो पांडेसिक

2
इसका उपयोग करो। <1 मिनट में हासिल किया जो मुझे पता लगाने में काफी समय लगा रहा था। इस पुस्तकालय को मुक्त रखने के लिए धन्यवाद।
नजीब

35

TryAddWithoutValidation का उपयोग करने का प्रयास करें

  var client = new HttpClient();
  client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");

4
काम नहीं करने से मुझे 'गलत शीर्षक वाला नाम मिलता है। सुनिश्चित करें कि हेडर का उपयोग HttpRequestMessage, HttpResponseMessage के साथ प्रतिक्रिया हेडर और HttpContent ऑब्जेक्ट्स के साथ सामग्री हेडर के साथ किया जाता है। '
मार्टिन लीटज

3
आप में से जो "काम कर रहे हैं" या "काम नहीं कर रहे हैं" की रिपोर्ट कर रहे हैं, इन दिनों HttpClient एक बहुत ही अस्पष्ट वस्तु है। कृपया पूर्ण नाम (स्थान) और .d असेंबली से इसकी सूचना दें।
ग्रेनडाकोडर

Misused header nameत्रुटि डॉटनैट कोर 2.2 के साथ पुष्टि की है। मुझे @ carlosfigueira के उत्तर stackoverflow.com/a/10679340/2084315 का उपयोग करना था ।
ps2goat

यह पूर्ण .net कार्य (4.7) के लिए काम करता है।
ज़कीमा

28

नेट निश्चित मानकों का पालन करना, अर्थात् है कि आप के लिए मजबूर करने की कोशिश करता है Content-Typeहैडर केवल अनुरोध सामग्री (उदा पर निर्दिष्ट किया जा सकता POST, PUT, आदि)। इसलिए, जैसा कि दूसरों ने संकेत दिया है, Content-Typeहेडर सेट करने का पसंदीदा तरीका HttpContent.Headers.ContentTypeसंपत्ति के माध्यम से है।

उस कहा के साथ, कुछ एपीआई (जैसे कि लिक्विडफाइल्स आपी , 2016-12-19 के अनुसार) को अनुरोध के Content-Typeलिए हेडर सेट करने की आवश्यकता होती है GET। .Net इस हेडर को स्वयं अनुरोध पर - यहां तक ​​कि उपयोग करने की अनुमति नहीं देगा TryAddWithoutValidation। इसके अलावा, आप Contentअनुरोध के लिए निर्दिष्ट नहीं कर सकते - भले ही यह शून्य-लंबाई का हो। जिस तरह से मैं इस के आसपास पाने के लिए लग सकता था प्रतिबिंब का सहारा लेना था। कोड (मामले में कुछ और की जरूरत है) है

var field = typeof(System.Net.Http.Headers.HttpRequestHeaders)
    .GetField("invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static) 
  ?? typeof(System.Net.Http.Headers.HttpRequestHeaders) 
    .GetField("s_invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
if (field != null)
{
  var invalidFields = (HashSet<string>)field.GetValue(null);
  invalidFields.Remove("Content-Type");
}
_client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "text/xml");

संपादित करें:

जैसा कि टिप्पणियों में कहा गया है, इस क्षेत्र के dll के विभिन्न संस्करणों में अलग-अलग नाम हैं। में GitHub पर स्रोत कोड , क्षेत्र वर्तमान में नामित किया गया है s_invalidHeaders। @David थॉम्पसन के सुझाव के अनुसार इसके लिए उदाहरण को संशोधित किया गया है।


1
यह फ़ील्ड अब s_invalidHeaders है, इसलिए निम्नलिखित का उपयोग संगतता सुनिश्चित करता है: var फ़ील्ड = typeof (System.Net.Http.Headp.HttpRequestHeaders) .GetField ("अमान्यहेडर्स", System.Reflection.BindingFlags.NonPublic. System.efindion.BindingFlags.S ?? typeof (System.Net.Http.Headers.HttpRequestHeaders) .GetField ("s_invalidHeaders", System.Reflection.BindingFlags.NonPublic। System.Reflection.BindingFlags.Static)
डेविड थॉम्पसन

2
धन्यवाद धन्यवाद धन्यवाद! कभी-कभी मेरी माउंट हैंग हो जाती है और जब मैं Microsoft API पर हिट करता हूं तो ड्रॉल निकलता है .. मैं आपकी बहुत सीधी पोस्ट देखकर इसे साफ कर पाया। बहुत बुरा नहीं है ..
गेरार्ड ओनली

1
मैं इस उलझन में हूँ कि यह कोड आपके द्वारा वर्णित भयावह त्रुटियों का कारण कैसे बनेगा। क्या आप अपने उपयोग के मामले और आपके द्वारा प्राप्त की जा रही त्रुटियों के बारे में अधिक जानकारी प्रदान कर सकते हैं?
इरोमेक

2
वाह। इससे भी अधिक वाह, कि Asp.net WebApi GET के तरीकों को स्पष्ट रूप से निर्दिष्ट करने के लिए Content-Type की आवश्यकता होती है = (
AlfeG

2
होली मॉली, मैं विश्वास नहीं कर सकता कि मुझे इसका सहारा लेना है। कब से। .NET फ्रेमवर्क यह जरूरतमंद है कि मैं Http हैडर सेक्शन में क्या जोड़ सकता हूं? घृणित।
mmix

17

.NET कोर के बारे में कुछ अतिरिक्त जानकारी (एक अनुरोध पर सामग्री-प्रकार की आपूर्ति करने के लिए निजी फ़ील्ड सेट करने के बारे में इरेडेम की पोस्ट पढ़ने के बाद, जो सामग्री नहीं देती है) ...

अपने कोड को डीबग करने के बाद, मैं प्रतिबिंब के माध्यम से सेट करने के लिए निजी फ़ील्ड नहीं देख सकता - इसलिए मैंने सोचा कि मैं समस्या को फिर से बनाने की कोशिश करूँगा।

मैंने निम्न कोड का उपयोग करने की कोशिश की है। नेट 4.6:

HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Get, @"myUrl");
httpRequest.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");

HttpClient client = new HttpClient();
Task<HttpResponseMessage> response =  client.SendAsync(httpRequest);  //I know I should have used async/await here!
var result = response.Result;

और, जैसा कि अपेक्षित था, मुझे सामग्री के साथ एक समग्र अपवाद मिलता है "Cannot send a content-body with this verb-type."

हालाँकि, अगर मैं .NET कोर (1.1) के साथ भी यही काम करता हूं - तो मुझे कोई अपवाद नहीं मिलता। मेरा अनुरोध मेरे सर्वर एप्लिकेशन द्वारा बहुत खुशी से उत्तर दिया गया था, और सामग्री-प्रकार उठाया गया था।

मैं इसके बारे में सुखद आश्चर्यचकित था, और मुझे आशा है कि यह किसी की मदद करता है!


1
धन्यवाद, जे - कोर का उपयोग नहीं, और erdomke के उत्तर का उपयोग करेगा। मैं यह जानकर सराहना करता हूं कि सभी उचित रास्ते आजमाए जा चुके हैं :)।
गेरार्ड ओनिल जूल

1
काम नहीं कर रहा है। नेट 4 ({"इस क्रिया-प्रकार के साथ एक कंटेंट-बॉडी नहीं भेज सकते हैं।")
तारेक एल-मल्लाह

3
@ तारेकेले-मल्लाह हां - कृपया मेरे उत्तर में टिप्पणियों को पढ़ें। मेरी पोस्ट का पूरा बिंदु यह बताना था कि यह .NET 4 में काम नहीं करता है, लेकिन यह .NET कोर में काम करता है (वे एक ही बात नहीं हैं)। आपको ओपी 4 में काम करने में सक्षम होने के लिए ओपी के सवाल का इरडोमेक जवाब देखना होगा।
जे।

16

AddWithoutValidationइसके बजाय कॉल करें Add( इस MSDN लिंक देखें )।

वैकल्पिक रूप से, मैं अनुमान लगा रहा हूं कि जिस एपीआई का आप वास्तव में उपयोग कर रहे हैं, उसके लिए केवल POST या PUT अनुरोध (साधारण GET अनुरोध नहीं) की आवश्यकता है। उस स्थिति में, जब आप कॉल करते हैं HttpClient.PostAsyncऔर एक पास HttpContentकरते Headersहैं, तो इसे उस HttpContentऑब्जेक्ट की संपत्ति पर सेट करें ।


काम नहीं करने से मुझे 'गलत शीर्षक वाला नाम मिलता है। सुनिश्चित करें कि हेडर का उपयोग HttpRequestMessage, HttpResponseMessage के साथ प्रतिक्रिया हेडर और HttpContent ऑब्जेक्ट्स के साथ सामग्री हेडर के साथ किया जाता है। '
मार्टिन लीटज

3
AddWithoutValidation मौजूद नहीं है
KansaiRobot

14

उन लोगों के लिए जो परेशान थे charset

मेरे पास बहुत विशेष मामला था कि सेवा प्रदाता ने charset स्वीकार नहीं किया, और उन्होंने इसे अनुमति देने के लिए उपप्रकार को बदलने से इनकार कर दिया ... दुर्भाग्य से HttpClient StringContent के माध्यम से हेडर को स्वचालित रूप से सेट कर रहा था, और कोई बात नहीं अगर आप अशक्त या Encoding .UTF8 पास करते हैं, यह हमेशा चारसेट सेट करेगा ...

आज मैं उप-प्रणाली को बदलने के लिए किनारे पर था; HttpClient से किसी और चीज की ओर बढ़ते हुए, कि मेरे दिमाग में कुछ आया ..., "चारसेट" को खाली करने के लिए प्रतिबिंब का उपयोग क्यों नहीं किया? ... और इससे पहले कि मैं भी कोशिश करूँ, मैंने एक तरीका सोचा, "शायद मैं इसे आरंभीकरण के बाद बदल सकता हूँ", और यह काम किया।

यहां बताया गया है कि आप सटीक "एप्लिकेशन / जोंस" हेडर को बिना सेट कैसे कर सकते हैं? चारसेट-यूटीएफ -8 "।

var jsonRequest = JsonSerializeObject(req, options); // Custom function that parse object to string
var stringContent = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
stringContent.Headers.ContentType.CharSet = null;
return stringContent;

नोट:null निम्नलिखित में मूल्य होगा काम नहीं है, और संलग्न "; charset = utf-8"

return new StringContent(jsonRequest, null, "application/json");

संपादित करें

@DesertFoxAZ सुझाव देता है कि निम्न कोड का भी उपयोग किया जा सकता है और ठीक काम करता है। (इसका परीक्षण खुद नहीं किया)

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

1
stringContent.Headers.ContentType = new MediaTypeHeaderValue ("एप्लिकेशन / जसन"); यह भी काम करता है
डेजर्टफोक्साज

4
var content = new JsonContent();
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("charset", "utf-8"));
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("IEEE754Compatible", "true"));

यह वह सब है जो आपको चाहिए।

Newtonsoft.Json का उपयोग करने के साथ, यदि आपको json string के रूप में सामग्री की आवश्यकता है।

public class JsonContent : HttpContent
   {
    private readonly MemoryStream _stream = new MemoryStream();
    ~JsonContent()
    {
        _stream.Dispose();
    }

    public JsonContent(object value)
    {
        Headers.ContentType = new MediaTypeHeaderValue("application/json");
        using (var contexStream = new MemoryStream())
        using (var jw = new JsonTextWriter(new StreamWriter(contexStream)) { Formatting = Formatting.Indented })
        {
            var serializer = new JsonSerializer();
            serializer.Serialize(jw, value);
            jw.Flush();
            contexStream.Position = 0;
            contexStream.WriteTo(_stream);
        }
        _stream.Position = 0;

    }

    private JsonContent(string content)
    {
        Headers.ContentType = new MediaTypeHeaderValue("application/json");
        using (var contexStream = new MemoryStream())
        using (var sw = new StreamWriter(contexStream))
        {
            sw.Write(content);
            sw.Flush();
            contexStream.Position = 0;
            contexStream.WriteTo(_stream);
        }
        _stream.Position = 0;
    }

    protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
    {
        return _stream.CopyToAsync(stream);
    }

    protected override bool TryComputeLength(out long length)
    {
        length = _stream.Length;
        return true;
    }

    public static HttpContent FromFile(string filepath)
    {
        var content = File.ReadAllText(filepath);
        return new JsonContent(content);
    }
    public string ToJsonString()
    {
        return Encoding.ASCII.GetString(_stream.GetBuffer(), 0, _stream.GetBuffer().Length).Trim();
    }
}

1
क्या आप इसका एक छोटा सा विवरण दे सकते हैं?
अलेजांद्रो

2
पहली पंक्ति CS0144 के साथ विफल होती है: "अमूर्त वर्ग या इंटरफ़ेस 'HttpContent' का एक उदाहरण नहीं बना सकता है
रैंडल फ्लैग

1
और फिरHttpMessageHandler handler = new WebRequestHandler(); HttpResponseMessage result; using (var client = (new HttpClient(handler, true))) { result = client.PostAsync(fullUri, content).Result; }
15:24 पर कला

2

ठीक है, यह HTTPClient नहीं है, लेकिन यदि आप इसका उपयोग कर सकते हैं, तो WebClient काफी आसान है:

using (var client = new System.Net.WebClient())
 {
    client.Headers.Add("Accept", "application/json");
    client.Headers.Add("Content-Type", "application/json; charset=utf-8");
    client.DownloadString(...);
 }

1

आप इसका उपयोग कर सकते हैं यह काम होगा!

HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Get,"URL");
msg.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");

HttpResponseMessage response = await _httpClient.SendAsync(msg);
response.EnsureSuccessStatusCode();

string json = await response.Content.ReadAsStringAsync();

0

मुझे यह सबसे सरल और समझने में आसान लगता है:

async Task SendPostRequest()
{
    HttpClient client = new HttpClient();
    var requestContent = new StringContent(<content>);
    requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    var response = await client.PostAsync(<url>, requestContent);
    var responseString = await response.Content.ReadAsStringAsync();
}
...

SendPostRequest().Wait();

0

आपको इसे इस तरह करने की आवश्यकता है:

    HttpContent httpContent = new StringContent(@"{ the json string }");
    httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));                
    HttpResponseMessage message = client.PostAsync(@"{url}", httpContent).Result;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.