添加HttpClient标头会生成带有某些值的FormatException


83

这是在针对Google Cloud Messaging进行编码的情况下发生的,但在其他地方也适用。

考虑以下:

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尝试将消息发布到GCN API-这要求使用上述格式将身份验证信息作为标头发送。但是,这是关于HttpClient标头的允许值的更一般的问题。
Andrew

Answers:


176

不确定是否仍然有用,但是我最近遇到了同样的问题,可以通过调用其他方法添加标头信息来解决此问题:

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

2
如果您不希望在默认标头中使用此方法,也可以在HttpRequestMessage上调用此方法
Ed Sykes 2014年

8
将此标记为答案,即使我仍然不明白为什么其他方法如果有效值验证失败。
2014年

1
此外,Windows 10的httpclient似乎无济于事
Sinaesthetic 2015年

4
我看到这是一个旧线程,但是我刚遇到了这个问题@EdSykes并尝试使用HttpRequestMessage它代替它,没有任何区别。该TryAddWithoutValidation方法对我有用。
马修·布洛特

23

对于“为什么所有这些(解析和验证)都是必要的”问题,答案是:它在HTTP标准中定义。

HTTP / 1.1RFC2617中,身份验证标头(例如WWW-Authenticate和Authorization)的值包含两个部分:方案部分和参数部分

对于HTTP基本身份验证,方案为“基本”,参数可能类似于“ QWxhZGRpbjpvcGVuIHNlc2FtZQ ==“,因此整个标头变为:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

这就是为什么您的“ key = XXX”没有通过验证的原因,因为它缺少方案部分。


在参数部分使用key = value是有效的。请参阅stackoverflow.com/a/19512506/55732
John Kurlak '16

1
@Kurlak:key = value仅对“ auth-param”部分有效,而对整个“ credentials”部分无效。CodeCaster的解释不太正确。
特里昌

3
我实际上使用的Bearer是方案,但仍向我显示错误。
汤姆

1
我在Bearer之后有个空格,例如“ Bearer”,这引起了问题。我在下面看到@Robert Stokes的答案,这对我有所帮助。
尚蒂

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 [] RowVersion SQL字段生成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]);                    
        }
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.