.Net Core
如果您自己设置头,则可以指定顺序。当添加公共标头时,它会查找现有标头而不是将其附加:
using System.Net;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
var request = WebRequest.Create("http://www.google.com");
request.Headers.Add("Host", "www.google.com");
request.Headers.Add("Connection", "");
request.Headers.Add("Accept", "*/*");
request.Headers.Add("User-Agent", "Mozilla/5.0 etc");
request.GetResponse();
}
}
}
下面是使用HttpClient
的一个例子:
using System.Net.Http;
using System.Threading.Tasks;
namespace ConsoleApp3
{
class Program
{
static async Task Main(string[] args)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Host", "www.google.com");
client.DefaultRequestHeaders.Add("Connection", "keep-alive");
client.DefaultRequestHeaders.Add("Accept", "*/*");
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 etc");
await client.GetAsync("http://www.google.com");
await client.PostAsync("http://www.google.com", new StringContent(""));
}
}
}
编辑
上面的代码只适用于 .Net Core,而不适用于 .Net Framework
.Net Framework
在 .Net Framework 上,这些标头被保留,因此无法像这样设置它们,请参见 Cannot set some HTTP headers when using System.Net.WebRequest。
一个解决方法是使用反射来修改框架类的行为,但请注意,如果库更新了,这可能会出现问题,因此不建议使用!
本质上,HttpWebRequest
在序列化时调用 WebHeaderCollection
的 ToString
方法。
请查看https://referencesource.microsoft.com/#System/net/System/Net/HttpWebRequest.cs,5079
因此,可以创建一个自定义类来覆盖 ToString
。不幸的是,需要使用反射来设置标头,因为 WebRequest
在分配给 Headers
时会复制集合,而不是采用新引用。
警告,以下代码可能会在框架更改时出现问题
如果您使用此代码,请编写一些单元测试以验证行为在更新 .NET Framework 后仍保持一致
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Reflection;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
var request = (HttpWebRequest)WebRequest.Create("http://www.google.com");
var field = typeof(HttpWebRequest).GetField("_HttpRequestHeaders", BindingFlags.Instance | BindingFlags.NonPublic);
var headers = new CustomWebHeaderCollection(new Dictionary<string, string>
{
["Host"] = "www.google.com",
["Connection"] = "keep-alive",
["Accept"] = "*/*",
["User-Agent"] = "Mozilla/5.0 etc"
});
field.SetValue(request, headers);
request.GetResponse();
}
}
internal class CustomWebHeaderCollection : WebHeaderCollection
{
private readonly Dictionary<string, string> _customHeaders;
public CustomWebHeaderCollection(Dictionary<string, string> customHeaders)
{
_customHeaders = customHeaders;
}
public override string ToString()
{
var lines = _customHeaders
.Select(kvp => $"{kvp.Key}: {kvp.Value}")
.Concat(new [] { string.Empty, string.Empty });
var headers = string.Join("\r\n", lines);
return headers;
}
}
}