HttpClientヘッダーを追加すると、いくつかの値を持つFormatExceptionが生成されます


83

これは、Googleクラウドメッセージングに対するコーディングのコンテキスト内で発生しましたが、他の場所でも当てはまります。

次のことを考慮してください。

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

そして

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

どちらもFormatExceptionを生成します。

System.FormatException:値key = XXX 'の形式が無効です。

解決策は、等号を削除することです。

  1. リフレクターを掘り下げると、新しいヘッダー値を追加するときに実行される検証と解析のコードがたくさんあることがわかります。なぜこれがすべて必要なのですか?このクライアントは私たちの邪魔にならないだけではいけませんか?

  2. この値の追加が成功するように、等号をどのようにエスケープしますか?


@SamIamがGCNAPIにメッセージを投稿しようとしています。これには、上記の形式を使用して認証情報をヘッダーとして送信する必要があります。ただし、これはHttpClientヘッダーに許可される値に関するより一般的な質問です。
アンドリュー

回答:


176

それでも関連があるかどうかはわかりませんが、最近同じ問題が発生し、別のメソッドを呼び出してヘッダー情報を追加することで解決できました。

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

2
デフォルトのヘッダーにこのメソッドを含めたくない場合は、HttpRequestMessageでこのメソッドを呼び出すこともできます
Ed Sykes

8
他のメソッドが有効な値である場合に検証に失敗する理由がまだわかりませんが、これを回答としてマークしました。
アンドリュー

1
また、Windows 10のhttpclientでは役に立たないようです
Sinaesthetic

4
これは古いスレッドだと思いますが、この問題@EdSykesに遭遇し、HttpRequestMessage代わりに使用してみましたが、違いはありませんでした。そのTryAddWithoutValidation方法は私のためにトリックをしました。
Matthew Blott 2016

23

「なぜこれ(解析と検証)がすべて必要なのか」という質問に対する答えは、HTTP標準で定義されているということです。

HTTP / 1.1及びRFC2617:、値(例えばWWW認証および認可など)認証ヘッダーは、二つの部分がありスキーム部、およびパラメータ部分

HTTP基本認証の場合、スキームは「Basic」であり、パラメーターは「QWxhZGRpbjpvcGVuIHNlc2FtZQ ==」のようになる可能性があるため、ヘッダー全体は次のようになります。

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

そのため、「key = XXX」はスキーム部分がないため、検証に合格しません。


パラメータセクションにkey = valueがあることは有効です。stackoverflow.com/a/19512506/55732を参照してください。
John Kurlak 2016

1
@Kurlak:key = valueは、「credentials」部分全体ではなく、「auth-param」部分にのみ有効です。CodeCasterの解釈は完全に正しくありません。
テリーチャン

3
私は実際に使用しています Bearerスキームとしてしていますが、それでもエラーが表示されます。
トム

1
ベアラーの後に「ベアラー」のようなスペースがあり、問題を引き起こしていました。私はそれを見るのを助けた以下の@RobertStokesの答えを見ました。
シャンティ

7

次の方法でAuthorizationヘッダーを設定することで、この例外(値のコンマが原因のFormatException)を回避しました。

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

4

Authorizationヘッダーの最後にスペースを追加したときに、このエラーが発生し、この投稿に遭遇しました。

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

承認後、問題のある「」が表示されます。

タイプミスが表示されるまでに約15分かかりました...


1

私は今朝、HTTP仕様に準拠していない外部APIを扱っているときに、いくつかの質問をしました。

私の投稿の一環として、彼らがしたいContent-TypeContent-Dispositionに追加することができない、HttpClientオブジェクト。これらのヘッダーを追加するには、HttpRequestMessageを作成する必要があります。そこで、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;
}

0

私の場合、byte [] RowVersionSQLフィールドからETags文字列値を生成しています。だから私は生成されたラップを追加する必要があります。すなわち、AAAAAAAAF5s =次のように "内の文字列...

        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]);                    
        }
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.