所有之前的回答都描述了问题,但未提供解决方案。这里有一个扩展方法,它可以通过允许您使用其字符串名称设置任何标题来解决该问题。
用法
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.SetRawHeader("content-type", "application/json");
扩展类
public static class HttpWebRequestExtensions
{
static string[] RestrictedHeaders = new string[] {
"Accept",
"Connection",
"Content-Length",
"Content-Type",
"Date",
"Expect",
"Host",
"If-Modified-Since",
"Keep-Alive",
"Proxy-Connection",
"Range",
"Referer",
"Transfer-Encoding",
"User-Agent"
};
static Dictionary<string, PropertyInfo> HeaderProperties = new Dictionary<string, PropertyInfo>(StringComparer.OrdinalIgnoreCase);
static HttpWebRequestExtensions()
{
Type type = typeof(HttpWebRequest);
foreach (string header in RestrictedHeaders)
{
string propertyName = header.Replace("-", "");
PropertyInfo headerProperty = type.GetProperty(propertyName);
HeaderProperties[header] = headerProperty;
}
}
public static void SetRawHeader(this HttpWebRequest request, string name, string value)
{
if (HeaderProperties.ContainsKey(name))
{
PropertyInfo property = HeaderProperties[name];
if (property.PropertyType == typeof(DateTime))
property.SetValue(request, DateTime.Parse(value), null);
else if (property.PropertyType == typeof(bool))
property.SetValue(request, Boolean.Parse(value), null);
else if (property.PropertyType == typeof(long))
property.SetValue(request, Int64.Parse(value), null);
else
property.SetValue(request, value, null);
}
else
{
request.Headers[name] = value;
}
}
}
场景
我为HttpWebRequest
编写了一个包装器,并不想将所有13个受限制的标头暴露为包装器中的属性。相反,我想使用一个简单的Dictionary<string, string>
。
另一个例子是HTTP代理,在其中您需要获取请求中的标头并将其转发给接收方。
还有很多其他情况下,使用属性并不实用或可能性不大。强制用户通过属性设置标题是非常不灵活的设计,这就是为什么需要反射。好处是反射被抽象化,它仍然很快(在我的测试中为0.001秒),并且作为扩展方法感觉很自然。
注意事项
根据RFC,标题名称不区分大小写,http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
Headers.Add()
添加的属性已经存在,因此我们应该进行修改而不是添加。 - Junaid Qadir Shekhanzai