是否有更多 elegant/clean 方法使用 TryAddWithoutValidation 方法设置 HttpRequestMessage Headers?

Is there a more elegant/clean way to set HttpRequestMessage Headers using TryAddWithoutValidation method?

我在几个方法中使用来自 HttpClient 的 HttpRequestMessage,目前,我在我的代码中重复以下代码片段:

此代码由 https://curl.olsh.me/ 转换,因此我不确定此处是否使用了最佳实践。

// using System.Net.Http;
using (var httpClient = new HttpClient(handler))
 {
     using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://www.url.com/"))
                {
                    request.Headers.TryAddWithoutValidation("authority", "www.url.com");
                    request.Headers.TryAddWithoutValidation("pragma", "no-cache");
                    request.Headers.TryAddWithoutValidation("cache-control", "no-cache");
                    request.Headers.TryAddWithoutValidation("dnt", "1");
                    request.Headers.TryAddWithoutValidation("x-requested-with", "XMLHttpRequest");
                    request.Headers.TryAddWithoutValidation("x-odesk-csrf-token", "19b91748869456a4ae700ffb69077745");
                    request.Headers.TryAddWithoutValidation("user-agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36");
                    request.Headers.TryAddWithoutValidation("accept", "*/*");
                    request.Headers.TryAddWithoutValidation("origin", "https://www.url.com");
                    request.Headers.TryAddWithoutValidation("sec-fetch-site", "same-origin");
                    request.Headers.TryAddWithoutValidation("sec-fetch-mode", "cors");
                    request.Headers.TryAddWithoutValidation("sec-fetch-dest", "empty");
                    request.Headers.TryAddWithoutValidation("referer", "https://www.url.com/");
                    request.Headers.TryAddWithoutValidation("accept-language", "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,fr-FR;q=0.6,fr;q=0.5");
                    request.Headers.TryAddWithoutValidation("cookie", "G_AUTHUSER_H=1; AccountSecurity_cat=fc4d14f1.oauth2v2_812293");
                    request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

                    var response = await httpClient.SendAsync(request);

                    IEnumerable<string> cookies = new List<string>();
                    response.Headers.TryGetValues("Set-Cookie", out cookies);

我假设您正在尝试了解如何将有问题的代码提取到辅助方法中,因为它使用了 using 块。如果没有,请澄清,我会调整我的答案。在这种情况下,我会这样做:

Task<HttpResponseMessage> PostAsyncWithHeaders(Uri uri)
{
    var response = new Task<HttpResponseMessage>();

    using (var httpClient = new HttpClient(handler))
    using (var request = new HttpRequestMessage(HttpMethod.Post, uri))
    {
        //Add your headers as before

        response = await httpClient.SendAsync(request);
    }

    return response;
}

然后您可以从任何可访问的地方调用该方法,如下所示:

response = await PostAsyncWithHeaders(new Uri("https://www.url.com/"));

IEnumerable<string> cookies = new List<string>();
response.Headers.TryGetValues("Set-Cookie", out cookies);
//Presumably consume cookies (yum!)

我在 .NET Core 3 中做了这个测试以供参考。

如果您希望能够在整个代码库中重用您的方法,您可以尝试如下操作:

 static async Task Main(string[] args)
    {
        var client = new HttpClient();

        // .NET core setting the content type.
        client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");

        // this is wrapped in the using statement.
        using var requestMessage = GetRequestMessage("https://www.url.com/", HttpMethod.Post);
        await client.SendAsync(requestMessage);
    }

    // Get the request message for reuse. You can then reuse this for maybe different end-points and method types. 
    // the "referer" or "origin" values can be passed in as parameters too. 
    static HttpRequestMessage GetRequestMessage(string url, HttpMethod method)
    {
        var request = new HttpRequestMessage(method, url);

        request.Headers.TryAddWithoutValidation("authority", "www.url.com");
        request.Headers.TryAddWithoutValidation("pragma", "no-cache");
        request.Headers.TryAddWithoutValidation("cache-control", "no-cache");
        request.Headers.TryAddWithoutValidation("dnt", "1");
        request.Headers.TryAddWithoutValidation("x-requested-with", "XMLHttpRequest");
        request.Headers.TryAddWithoutValidation("x-odesk-csrf-token", "19b91748869456a4ae700ffb69077745");
        request.Headers.TryAddWithoutValidation("user-agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36");
        request.Headers.TryAddWithoutValidation("accept", "*/*");
        request.Headers.TryAddWithoutValidation("origin", "https://www.url.com");
        request.Headers.TryAddWithoutValidation("sec-fetch-site", "same-origin");
        request.Headers.TryAddWithoutValidation("sec-fetch-mode", "cors");
        request.Headers.TryAddWithoutValidation("sec-fetch-dest", "empty");
        request.Headers.TryAddWithoutValidation("referer", "https://www.url.com/");
        request.Headers.TryAddWithoutValidation("accept-language", "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,fr-FR;q=0.6,fr;q=0.5");
        request.Headers.TryAddWithoutValidation("cookie", "G_AUTHUSER_H=1; AccountSecurity_cat=fc4d14f1.oauth2v2_812293");
        
        return request;
    }

如果您在控制台程序中使用它,您可以在 using 语句中创建 HttpClient。但是,如果您打算在 .net core 中的 web 应用程序中使用客户端,则需要使用 services.AddHttpClient 方法和依赖注入。这是因为 HttpClient 并非旨在在每次使用后都被处理掉,尤其是如果您在给定的调用中多次使用它。

非常感谢@Jaquez 和@Kuroiyatsu 的回答,我得到了以下内容

 public async Task<string> postAsync(param1, param2)
{
    using (var httpClient = new HttpClient(handler))
    {
        using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://www.url.com/"))
        {

....

var response = await PostAsync(param1, param2);

var variable = JsonSerializer.Deserialize<Obj>(response);

WebScrapFunc(response);

...

虽然从 PostAsync 中 return 一个 Task<string> 看起来很奇怪,但它符合我的意图。