1145 Stimmen

Wie legt man den Content-Type-Header für eine HttpClient-Anfrage fest?

Ich versuche, die Content-Type Kopfzeile eines HttpClient Objekt, wie es von einer API, die ich aufrufe, benötigt wird.

Ich habe versucht, die Einstellung Content-Type wie unten:

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");
    // ...
}

Sie ermöglicht es mir, die Accept Kopfzeile, aber wenn ich versuche, die Content-Type löst er die folgende Ausnahme aus:

Falsch verwendeter Kopfzeilenname. M HttpRequestMessage Antwort-Header mit HttpResponseMessage und Inhaltskopfzeilen mit HttpContent Objekte.

Wie kann ich die Content-Type Kopfzeile in einer HttpClient Anfrage?

1407voto

carlosfigueira Punkte 82509

Der Inhaltstyp ist eine Kopfzeile des Inhalts, nicht der Anfrage, weshalb dies fehlschlägt. AddWithoutValidation wie von Robert Levy vorgeschlagen funktionieren, aber Sie können den Inhaltstyp auch bei der Erstellung des Anforderungsinhalts selbst festlegen (beachten Sie, dass der Codeschnipsel application/json an zwei Stellen - für Accept- und Content-Type-Header):

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);
      });

233voto

archgl Punkte 2412

Für diejenigen, die Johns Kommentar zu Carlos Lösung nicht gesehen haben ...

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

64voto

Todd Menier Punkte 34732

Wenn Sie nichts gegen eine kleine Bibliotheksabhängigkeit haben, Flurl.Http (Offenlegung: Ich bin der Autor) macht dies super-einfach. Seine PostJsonAsync Methode kümmert sich sowohl um die Serialisierung des Inhalts als auch um das Setzen der content-type Kopfzeile, und ReceiveJson deserialisiert die Antwort. Wenn die accept Header erforderlich ist, müssen Sie das selbst einstellen, aber Flurl bietet eine ziemlich saubere Möglichkeit, das auch zu tun:

using Flurl.Http;

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

Flurl verwendet HttpClient und Json.NET unter der Haube, und es ist ein PCL, so dass es auf einer Vielzahl von Plattformen funktionieren wird.

PM> Install-Package Flurl.Http

50voto

erdomke Punkte 4580

.Net versucht, Sie zu zwingen, bestimmte Standards zu befolgen, nämlich dass die Content-Type Kopfzeile kann nur bei Anfragen angegeben werden, die einen Inhalt haben (z. B. POST , PUT , usw.). Daher ist, wie bereits von anderen erwähnt, die bevorzugte Methode zur Einstellung der Content-Type Kopfzeile ist durch die HttpContent.Headers.ContentType Eigentum.

Allerdings können bestimmte APIs (wie z. B. die LiquidFiles Api (Stand: 2016-12-19) erfordert die Einstellung der Content-Type Kopfzeile für eine GET Anfrage. .Net erlaubt es nicht, diesen Header in der Anfrage selbst zu setzen - auch nicht mit TryAddWithoutValidation . Außerdem können Sie nicht eine Content für die Anfrage - auch wenn sie null Länge hat. Die einzige Möglichkeit, dies zu umgehen, bestand darin, auf Reflexion zurückzugreifen. Der Code (für den Fall, dass ihn jemand anderes braucht) lautet

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");

Edit :

Wie in den Kommentaren erwähnt, hat dieses Feld in den verschiedenen Versionen der DLL unterschiedliche Namen. In der Quellcode auf GitHub heißt das Feld derzeit s_invalidHeaders . Das Beispiel wurde auf Vorschlag von @David Thompson geändert, um dies zu berücksichtigen.

49voto

SharpCoder Punkte 17283

versuchen, TryAddWithoutValidation zu verwenden

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X