Reputation: 43
My client code makes call to an API and I'm trying to get the returned ETag value from the response headers. If I use Fiddler I can see the response contains the ETag header and if I make API call using Postman I can see the ETag header, but no matter what approach I take to try and retrieve the headers in my code all I get returned is a null.
Essentially the API call is;
// 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
The Postman response is;
I've spent hours searching and trying examples from web, but no matter what I try I can't get the the ETag header.
Using the example code below I do get the first 2 headers as shown in the Postman response headers returned but not the ETag header / value.
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()
);
I'm using Visual Studio, Blazor and aspnetcore 5.0 and I'm looking to generate an PWA with IndexDB and use ETag's to reduce data downloads.
Any help on how to get to the Etag header will be much appreciated...
Upvotes: 3
Views: 5982
Reputation: 71
I had similar issue like other people. Actually we have github issue and great discussion that was open on this issue. I just want to share like with other people that are maybe stuck at same point and visit stack overflow.
Link for issue (closed):
https://github.com/dotnet/runtime/issues/42179
Quote from discussion "Your CORS policy needs to specify what headers are exposed. If you would like the client to read all headers, you can specify it as so"
Example(Server side):
services.AddCors(options =>
{
options.AddPolicy("Open", builder => builder
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.WithExposedHeaders("*")); // this is the important part!
});
Upvotes: 7
Reputation: 43
I created very simple console app and used that to GET data from API, I can see that the ETag value is being returned in the response but can't seem to simply extract the value in code, using 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;
}
}
}
I believe the issue is due to the project being a Blazor Web Assembly project, if I create simple .net core project then the following code works;
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();
However the same code in Blazor does not.
Upvotes: 1
Reputation: 2601
On the response message object, you can access the ETag header directly.
// 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;
Upvotes: 0