在不使用MediaTypeWithQualityHeaderValue的情况下设置Accept Header

MHO*_*OOS 5 c# web-services asp.net-web-api asp.net-web-api2

在Asp.Net Web Api 2中,使用以下传统方法设置HttpClient接受标头有什么区别:

        HttpClient client = HttpClientFactory.Create(handler);

        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Run Code Online (Sandbox Code Playgroud)

和以下方法:

var headers = new Dictionary<string, string>
            {
                {"Accept", "application/json"}};

headers.ForEach(h => client.DefaultRequestHeaders.Add(h.Key, h.Value));
Run Code Online (Sandbox Code Playgroud)

更新1:

根据以下帖子中@DarrenMiller的回答,在WebAPI客户端中每个调用创建一个新HttpClient的开销是多少?似乎首选方法正在使用DefaultRequestHeaders属性,因为它包含旨在用于多个调用的属性。这是否意味着如果我使用简单的字典设置默认标头,我的HttpClient client效率将不及使用它的那个DefaultRequestHeaders?另外我真的不明白里面的值DefaultRequestHeaders将如何被重用?可以说我创建了20个HttpClient clientHttpClientFactory.Create并在其中每个设置的20个内部设置了某种性能命中率?DefaultRequestHeaders产权[我真的需要这么做,因为DefaultRequestHeaders是为了被重用?!]。哪里该重用跳入和不设置DefaultRequestHeaders我创建了一个每次HttpClient client

Man*_*ion 1

您的问题的第一部分:添加标头有什么区别吗?

HttpClient client = HttpClientFactory.Create(handler);
Run Code Online (Sandbox Code Playgroud)

方法一:

client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Run Code Online (Sandbox Code Playgroud)

方法二:

var headers = new Dictionary<string, string>{{"Accept", "application/json"}};
headers.ForEach(h => client.DefaultRequestHeaders.Add(h.Key, h.Value));
Run Code Online (Sandbox Code Playgroud)

方法 1 为您提供了很好的强类型值,并且能够添加多个接受类型。方法 2 多了一个“魔术字符串”,可能会出现拼写错误,并且无法添加多个接受类型。

你的问题的第二部分:性能和重用价值在哪里?

对每个请求使用新的 HttpClient 的性能影响取决于您的用例。获取基准并进行测量,看看它是否重要。开发人员的表现很可能是收益所在。考虑到您使用的每个 HttpClient 都必须记住一堆要添加的标头。如果您忘记添加正确的标头,则会发生错误。因此,您可以使用 DefaultRequestHeaders 在工厂中进行设置。

public class ApiService
{
    public static HttpClient GetClient()
    {
        var client = new HttpClient(new Uri("https://someservice/"));
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
        //add any other setup items here.
        return client;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在使用它:

public async Task DoStuff()
{
    using(var client = ApiService.GetClient())
    {
        //client will have the proper base uri and all the headers set.
        var data = await client.GetAsync<dynamic>("Sales");

        //client will still have the proper base uri and all the headers set.
        var data2 = await client.GetAsync<dynamic>("Products");
    }
}
Run Code Online (Sandbox Code Playgroud)

HttpClients 应该是短暂的并且总是包含在 using 语句中。当使用同一客户端发出多个请求时,就会发生重用。

更新

正如其他人提到的,Microsoft 建议在应用程序的生命周期中保留一个 HttpClient,以避免过多的开销。获取 HttpClient 的首选方法是声明一个静态的,然后根据需要引用它。请注意,默认标头中设置的任何内容都会随每个请求一起出去,因此请确保不要将授权等内容放在那里,除非您确定请求的最终目的地。

  • “HttpClients 应该是短暂的” - 还有其他指导(例如:http://stackoverflow.com/a/22561368/306430)与此相矛盾。重建 HttpClient(并重新建立底层连接)可能会很昂贵,因此对于对性能和/或可扩展性敏感的站点,也可以长期重用 HttpClient。 (3认同)