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?

6voto

yoel halb Punkte 11337

Es scheint, dass Microsoft versucht, die Entwickler zu zwingen, ihre Standards zu befolgen, ohne auch nur irgendwelche Optionen oder Einstellungen zu geben, um etwas anderes zu tun, was wirklich eine Schande ist, vor allem, wenn man bedenkt, dass dies ein Client ist und wir von den serverseitigen Anforderungen diktiert werden, vor allem, wenn man bedenkt, dass die serverseitigen Frameworks von Microsoft selbst dies erfordern!

Im Grunde versucht Microsoft also, uns gute Gewohnheiten aufzuzwingen, wenn wir uns mit ihren Servertechnologien verbinden, die uns zu nicht guten Gewohnheiten zwingen...

Wenn irgendjemand von Microsoft dies liest, dann bringen Sie es bitte in Ordnung...

So oder so für jeden, der den Content-Type-Header für Get etc. benötigt, während es in einer älteren .Net-Version möglich ist, die Antwort von @erdomke zu verwenden https://stackoverflow.com/a/41231353/640195 dies funktioniert leider nicht mehr in den neueren .Net-Kernversionen.

Der folgende Code wurde mit .Net Core 3.1 getestet, und aus dem Quellcode auf GitHub geht hervor, dass er auch mit neueren .Net-Versionen funktionieren sollte.

private void FixContentTypeHeaders()
{
    var assembly = typeof(System.Net.Http.Headers.HttpRequestHeaders).Assembly;
    var assemblyTypes = assembly.GetTypes();

    var knownHeaderType = assemblyTypes.FirstOrDefault(n => n.Name == "KnownHeader");
    var headerTypeField = knownHeaderType?
                .GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
                .FirstOrDefault(n => n.Name.Contains("HeaderType"));
    if (headerTypeField is null) return;

    var headerTypeFieldType = headerTypeField.FieldType;            
    var newValue = Enum.Parse(headerTypeFieldType, "All");

    var knownHeadersType = assemblyTypes.FirstOrDefault(n => n.Name == "KnownHeaders");
    var contentTypeObj = knownHeadersType.GetFields().FirstOrDefault(n => n.Name == "ContentType").GetValue(null);

    if (contentTypeObj is null) return;

    headerTypeField.SetValue(contentTypeObj, newValue);
}

4voto

art24war Punkte 57
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"));

Es ist alles, was Sie brauchen.

Bei der Verwendung von Newtonsoft.Json, wenn Sie einen Inhalt als Json-String benötigen.

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

3voto

Ziba Leah Punkte 2424

Ok, es ist nicht HTTPClient, aber wenn Sie es verwenden können, ist WebClient ziemlich einfach:

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

3voto

Sérgio Damasceno Punkte 637

Ich habe die Antwort mit RestSharp erhalten:

        private async Task<string> GetAccessTokenAsync()
        {
            var client = new RestClient(_baseURL);

            var request = new RestRequest("auth/v1/login", Method.POST, DataFormat.Json);

            request.AddHeader("Content-Type", "application/json");
            request.AddHeader("x-api-key", _apiKey);
            request.AddHeader("Accept-Language", "br");
            request.AddHeader("x-client-tenant", "1");

            ...
        }

Bei mir hat es funktioniert.

3voto

Felipe Augusto Punkte 878

Versuchen, HttpClientFactory zu verwenden

services.AddSingleton<WebRequestXXX>()
        .AddHttpClient<WebRequestXXX>("ClientX", config =>
        {
           config.BaseAddress = new System.Uri("https://jsonplaceholder.typicode.com");
           config.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
           config.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
        });

\======================

public class WebRequestXXXX
{
    private readonly IHttpClientFactory _httpClientFactory;

    public WebRequestXXXX(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    public List<Posts> GetAllPosts()
    {
        using (var _client = _httpClientFactory.CreateClient("ClientX"))
        {
            var response = _client.GetAsync("/posts").Result;

            if (response.IsSuccessStatusCode)
            {
                var itemString = response.Content.ReadAsStringAsync().Result;
                var itemJson = System.Text.Json.JsonSerializer.Deserialize<List<Posts>>(itemString, 
                    new System.Text.Json.JsonSerializerOptions 
                    {
                        PropertyNameCaseInsensitive = true
                    });

                return itemJson;
            }
            else
            {
                return new List<Posts>();
            }
        }
    }
}

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