如何在 Blazor WASM 客户端中访问 Httpclient 标头

Posted

技术标签:

【中文标题】如何在 Blazor WASM 客户端中访问 Httpclient 标头【英文标题】:How to access Httpclient headers in Blazor WASM Client 【发布时间】:2021-03-31 16:58:15 【问题描述】:

我的客户端代码调用了一个 API,我试图从响应标头中获取返回的 ETag 值。如果我使用 Fiddler,我可以看到响应包含 ETag 标头,如果我使用 Postman 进行 API 调用,我可以看到 ETag 标头,但是无论我采用什么方法尝试检索代码中的标头,我得到的只是一个空。

本质上是 API 调用;

// create request object
var request = new HttpRequestMessage(HttpMethod.Get, url);
// add authorization header
request.Headers.Authorization = new AuthenticationHeaderValue("bearer", await GetBearerToken());
// send request
HttpResponseMessage response = await _client.SendAsync(request);

Fiddler Response Header showing Etag

邮递员的回应是;

Postman response headers

我花了几个小时从网络上搜索和尝试示例,但无论我尝试什么,我都无法获得 ETag 标头。

使用下面的示例代码,我确实获得了前 2 个标头,如返回的 Postman 响应标头中所示,但不是 ETag 标头/值。

String allResponseHeaders = Enumerable
    .Empty<(String name, String value)>()
    .Concat(
    response.Headers
    .SelectMany(kvp => kvp.Value
    .Select(v => (name: kvp.Key, value: v))
    ))
    .Concat(
    response.Content.Headers
    .SelectMany(kvp => kvp.Value
    .Select(v => (name: kvp.Key, value: v))
    ))
   .Aggregate(
   seed: new StringBuilder(),
   func: (sb, pair) => sb.Append(pair.name).Append(": ").Append(pair.value).AppendLine(),
   resultSelector: sb => sb.ToString()
   );

我正在使用 Visual Studio、Blazor 和 aspnetcore 5.0,我希望使用 IndexDB 生成 PWA,并使用 ETag 来减少数据下载。

任何有关如何获取 Etag 标头的帮助将不胜感激...

【问题讨论】:

【参考方案1】:

我和其他人有类似的问题。实际上,我们有 github 问题和关于这个问题的精彩讨论。我只是想与其他可能卡在同一点并访问堆栈溢出的人分享。

问题链接(已关闭):

https://github.com/dotnet/runtime/issues/42179

引用讨论“您的 CORS 策略需要指定公开哪些标头。如果您希望客户端读取所有标头,您可以这样指定”

示例(服务器端):

services.AddCors(options =>

    options.AddPolicy("Open", builder => builder
        .AllowAnyOrigin()
        .AllowAnyHeader()
        .AllowAnyMethod()
        .WithExposedHeaders("*")); // this is the important part!
);

【讨论】:

Dino,非常感谢这次更新,我差点放弃让 eTag 与 Blazor WASM 一起工作。但是,我只是按照您的说明添加了 .WithExposedHeaders("*") 并返回了 eTag 标头。我仍然有一个问题,为什么 Postman 在 API 服务器中没有该设置的情况下获取 eTag 标头,而 Blazor WASM 没有,但这可能是另一天......再次感谢......【参考方案2】:

我创建了非常简单的控制台应用程序并使用它从 API 获取数据,我可以看到响应中返回了 ETag 值,但似乎无法使用 response.Headers.Etag 简单地提取代码中的值.

using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace SimpleAPIClient


    class Program
    
        private static readonly HttpClient client = new HttpClient();

        static async Task Main(string[] args)
        

            var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:44338/api/headers/3");
            request.Headers.Authorization = new AuthenticationHeaderValue("bearer", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbkBjb250cmEtc29mdC5jb20iLCJqdGkiOiI4NjgyMmQ1YS1iNTQ3LTRlMjItYmQ3NS0wNDlkZmE5MTMzZmUiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjVkODExZmY1LTgyY2QtNDY2NC05ODkzLTZmNGRjMDU0YzFmNSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6IkFkbWluaXN0cmF0b3IiLCJleHAiOjE2MDgzNTU0MTEsImlzcyI6ImNvbnRyYS1zb2Z0LmNvbSIsImF1ZCI6ImNvbnRyYS1zb2Z0LmNvbSJ9.w_CSstMZkFFn0DcMlcPNNm_Nr0idzHPo6I2hRjEUglQ");
            HttpResponseMessage response = await client.SendAsync(request);

            var etag = response.Headers.ETag;

            int i = 0;
        

    

VS Breakpoint shows ETag data

我认为问题是由于该项目是 Blazor Web Assembly 项目,如果我创建简单的 .net 核心项目,则以下代码可以工作;

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiO");
Task<HttpResponseMessage> s = client.GetAsync("https://localhost:44338/api/headers/3");
HttpResponseMessage nresponse2 = await s;
var etag2 = nresponse2.Headers.FirstOrDefault(i => i.Key == "ETag").Value.FirstOrDefault();

但是 Blazor 中的相同代码却没有。

【讨论】:

你能用 .Content.Headers 比如response.Content.Headers.ETag 试试吗? 问题在于 Blazor Web Assembly 项目,如果我创建控制台应用程序,则下面的代码有效;【参考方案3】:

在响应消息对象上,可以直接访问 ETag 标头。

// create request object
var request = new HttpRequestMessage(HttpMethod.Get, url);
// add authorization header
request.Headers.Authorization = new AuthenticationHeaderValue("bearer", await GetBearerToken());
// send request
HttpResponseMessage response = await _client.SendAsync(request);

//read the response headers. The ETag is already a "known" header and is easily accessible via a property
EntityTagHeaderValue etagHeader = response.Headers.ETag;

【讨论】:

感谢您的回复,我尝试了类似的选项,现在我已经尝试了您的代码,但返回的值仍然为空。我刚刚使用 restsharp 和 .net 4.7.2 制作了一个简单的控制台应用程序,并且可以看到所有标题,因此要创建简单的 aspnetcore 控制台应用程序来查看 httpclient 是否有效,将尝试版本 3.1 和 5.0

以上是关于如何在 Blazor WASM 客户端中访问 Httpclient 标头的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Azure AD B2C 保护 Blazor Wasm 应用访问的 Azure 函数?

Blazor 客户端 (WASM) 应用程序洞察

在刷新页面之前,Blazor Web Assembly (wasm) 不会使客户端 cookie 过期

如何在 ASP .NET Core Web API 中映射回退,以便 Blazor WASM 应用程序仅拦截未发送到 API 的请求

使用 Blazor wasm Bearer Token 进行 SignalR 身份验证

Blazor WASM AzureAD IdentityServer 导致 AADSTS90023:公共客户端无法发送客户端密码