Durch Hinzufügen von HttpClient-Headern wird eine FormatException mit einigen Werten generiert


83

Dies geschah im Rahmen der Codierung gegen Google Cloud Messaging, gilt jedoch an anderer Stelle.

Folgendes berücksichtigen:

var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("key=XXX");

und

var http = new HttpClient();
http.DefaultRequestHeaders.Add("Authorization", "key=XXX");

Beide generieren eine FormatException:

System.FormatException: Das Format des Wertschlüssels = XXX 'ist ungültig.

Die Lösung besteht darin, das Gleichheitszeichen zu entfernen.

  1. Das Durchsuchen des Reflektors zeigt, dass es Unmengen von Validierungs- und Parsing-Code gibt, die ausgeführt werden, wenn ein neuer Header-Wert hinzugefügt wird. Warum ist das alles notwendig? Sollte dieser Kunde uns nicht einfach aus dem Weg gehen?

  2. Wie entkommen Sie dem Gleichheitszeichen, damit das Hinzufügen dieses Werts erfolgreich ist?


@SamIam versucht, eine Nachricht an die GCN-API zu senden. Dazu müssen Authentifizierungsinformationen als Header im oben gezeigten Format gesendet werden. Dies ist jedoch eine allgemeinere Frage zu den zulässigen Werten für HttpClient-Header.
Andrew

Antworten:


176

Ich bin mir nicht sicher, ob es noch relevant ist, aber ich bin kürzlich auf dasselbe Problem gestoßen und konnte es lösen, indem ich eine andere Methode zum Hinzufügen der Header-Informationen aufrief:

var http = new HttpClient();
http.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "key=XXX");

2
Sie können diese Methode auch auf HttpRequestMessage aufrufen, wenn Sie sie nicht in den Standardheadern haben möchten
Ed Sykes

8
Markierte dies als Antwort, obwohl ich immer noch nicht verstehe, warum die andere Methode bei der Validierung fehlschlägt, wenn es sich um einen gültigen Wert handelt.
Andrew

1
Auch scheint in Windows 10 httpclient
Sinaesthetic

4
Ich sehe, dass dies ein alter Thread ist, aber ich bin gerade auf dieses Problem @EdSykes gestoßen und habe versucht, es HttpRequestMessagestattdessen zu verwenden, und es machte keinen Unterschied. Die TryAddWithoutValidationMethode hat den Trick für mich getan.
Matthew Blott

23

Auf Ihre Frage "Warum ist all dies (Analyse und Validierung) notwendig?" Lautet die Antwort: Sie ist im HTTP-Standard definiert.

In HTTP / 1.1 und RFC2617 besteht der Wert eines Authentifizierungsheaders (z. B. WWW-Authentifizierung und Autorisierung) aus zwei Teilen: einem Schemateil und einem Parameterteil .

Für die HTTP- Basisauthentifizierung lautet das Schema "Basis", und der Parameter kann etwa "QWxhZGRpbjpvcGVuIHNlc2FtZQ ==" lauten , sodass der gesamte Header wie folgt lautet :

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Aus diesem Grund besteht Ihr "key = XXX" die Validierung nicht, da ihm ein Schemateil fehlt.


Der Wert = Wert im Parameterabschnitt ist gültig. Siehe stackoverflow.com/a/19512506/55732 .
John Kurlak

1
@Kurlak: key = value gilt nur für den Teil "auth-param", nicht für den gesamten Teil "credentials". Die Interpretation von CodeCaster ist nicht ganz richtig.
Terry Chang

3
Ich verwende es tatsächlich Bearerals Schema, aber es zeigt mir immer noch den Fehler.
Tom

1
Ich hatte ein Leerzeichen nach Bearer wie "Bearer", das Probleme verursachte. Ich habe unten die Antwort von @Robert Stokes gesehen, die mir geholfen hat, sie zu sehen.
Shanti

7

Ich habe diese Ausnahme (meine FormatException, die durch Kommas im Wert verursacht wird) umgangen, indem ich den Authorization-Header folgendermaßen festgelegt habe:

var authenticationHeaderValue = new AuthenticationHeaderValue("some scheme", "some value");
client.DefaultRequestHeaders.Authorization = authenticationHeaderValue;

Dies ist die richtigste Antwort
andreapier

4

Ich bin auf diesen Fehler gestoßen und bin auf diesen Beitrag gestoßen, als ich am Ende eines Autorisierungsheaders ein Leerzeichen eingefügt habe.

this.bearerAuthHttpClient.DefaultRequestHeaders.Add("Authorization ", $"Bearer {token}");

Sie können das beleidigende "" nach der Autorisierung sehen.

Es dauerte ungefähr 15 Minuten, bis ich meinen Tippfehler sah ...


1

Ich habe heute Morgen einige Fragen durchgearbeitet, während ich mich mit einer externen API befasst habe, die nicht genau der HTTP-Spezifikation entspricht.

Als Teil meines Beitrags möchten sie das Content-Typeund Content-Disposition, das dem HttpClientObjekt nicht hinzugefügt werden kann. Um diese Header hinzuzufügen, müssen Sie eine HttpRequestMessage erstellen . Dort müssen Sie die Header zur ContentEigenschaft hinzufügen .

private HttpRequestMessage GetPostMessage(string uri, string contentType,
                                          string fileName, Stream content)
{    
    var request = new HttpRequestMessage
    {
        Content = new StreamContent(content),
        RequestUri = new Uri(uri),
        Method = HttpMethod.Post
    };

    // contentType = "video/mp4"
    request.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);

    //Need TryAddWithoutValidation because of the equals sign in the value.
    request.Content
           .Headers
           .TryAddWithoutValidation("Content-Disposition",
                                    $"attachment; filename=\"{Path.GetFileName(fileName)}\"");

    // If there is no equals sign in your content disposition, this will work:
    // request.Content.Headers.ContentDisposition = 
    //    new ContentDispositionHeaderValue($"attachment; \"{Path.GetFileName(fileName)}\"");

    return request;
}

0

In meinem Fall generiere ich ETags-Zeichenfolgenwerte aus einem Byte [] RowVersion SQL-Feld. Also muss ich den generierten Wrap hinzufügen. dh AAAAAAAAF5s = Zeichenfolge innerhalb "wie folgt ...

        var eTag = department.RowVersion.ToETagString();

        httpClient.DefaultRequestHeaders.Add(Microsoft.Net.Http.Headers.HeaderNames.IfMatch, $"\"{eTag}\"")


    public class DepartmentForHandleDto
    {
        public string Name { get; set; }
        public string GroupName { get; set; }
        public byte[] RowVersion { get; set; }
    }

    public static class ByteArrayExtensions
    {
        public static string ToETagString(this byte[] byteArray)
        {
            return Convert.ToBase64String(byteArray != null && byteArray.Length > 0 ? byteArray : new byte[8]);                    
        }
    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.