web-dev-qa-db-fra.com

L'ajout d'en-têtes HttpClient génère une exception FormatException avec certaines valeurs

Cela s'est produit dans le contexte du codage de Google Cloud Messaging, mais s'applique ailleurs.

Considérer ce qui suit:

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

et

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

qui génèrent tous deux une FormatException:

System.FormatException: le format de la valeur clé = XXX 'n'est pas valide.

La solution consiste à supprimer le signe égal.

  1. Creuser dans le réflecteur montre qu'il y a une myriade de code de validation et d'analyse qui s'exécute lors de l'ajout d'une nouvelle valeur d'en-tête. Pourquoi tout cela est-il nécessaire? Ce client ne devrait-il pas simplement sortir de notre chemin?

  2. Comment échapper au signe d'égalité pour que l'ajout de cette valeur réussisse?

54
Andrew

Pas sûr que cela soit toujours pertinent, mais j'ai récemment rencontré ce même problème et j'ai pu le résoudre en appelant une méthode différente pour ajouter les informations d'en-tête:

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

A votre question "Pourquoi est-ce que tout cela est nécessaire (analyse et validation)", la réponse est: elle est définie dans la norme HTTP. 

Dans HTTP/1.1 et RFC2617 , la valeur d'un en-tête d'authentification (tel que WWW-Authenticate and Authorization) comporte deux parties: une partie de schéma et une partie de paramètre

Pour l'authentification HTTP de base, le schéma est "De base" et le paramètre peut ressembler à quelque chose comme "QWxhZGRpbjpvcGVuIHNlc2FtZQ ==", l'en-tête devient ainsi

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

C'est pourquoi votre "clé = XXX" ne passe pas la validation, car il lui manque une partie schéma.

16
Terry Chang

J'ai contourné cette exception (mon exception FormatException causée par des virgules dans la valeur) en définissant l'en-tête Authorization de la manière suivante:

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

J'ai rencontré cette erreur et suis tombé sur ce message lorsque j'ai ajouté un espace à la fin d'un en-tête d'autorisation.

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

Vous pouvez voir le "" fautif après l'autorisation.

Il m'a fallu environ 15 minutes avant de voir ma faute de frappe ...

2
Robert Stokes

J'ai eu quelques questions à vous poser ce matin alors que je travaillais avec une API externe qui ne respecte pas à la lettre les spécifications HTTP.

Dans le cadre de ma publication, ils veulent le Content-Type et le Content-Disposition, qui ne peuvent pas être ajoutés à l'objet HttpClient. Pour ajouter ces en-têtes, vous devez créer un HttpRequestMessage . Là-dessus, vous devez ajouter les en-têtes à la propriété Content.

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;
}
1
krillgar

Dans mon cas, je génère des valeurs de chaîne ETags à partir d'un champ SQL byte [] RowVersion . Il me faut donc ajouter à la ligne le produit généré. AAAAAAAAF5s = chaîne à l'intérieur "comme suit ... 

        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]);                    
        }
    }
0
alhpe