I created a simple asp.net Web API that sends users from a SQL table.The API requires a key in the request header. I'm now creating a simple Blazor WebAssembly App that shows the users. I am just adding a simple httpclient:
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("https://localhost:7280/")});
and then I create the typical crud operations. For example the request for all the users:
public class UserService : IUserService
{
private readonly HttpClient httpClient;
public UserService(HttpClient httpClient)
{
this.httpClient = httpClient;
}
public async Task<List<UserDto>> GetUsers()
{
try
{
var response = await this.httpClient.GetAsync("api/Users");
if (response.IsSuccessStatusCode)
{
if (response.StatusCode == System.Net.HttpStatusCode.NoContent)
{
return Enumerable.Empty<UserDto>().ToList();
}
return await response.Content.ReadFromJsonAsync<List<UserDto>>();
}
else
{
var alert = await response.Content.ReadAsStringAsync();
throw new Exception($"Http status:{response.StatusCode} - {alert}");
}
}
catch (Exception)
{
throw;
}
}
}
Is there a way to add header to all requests? Or do I have to make a custom request every time?
CodePudding user response:
The standard pattern for adding behavior for all of your HTTP requests is to use DelegatingHandler
. For your purposes, first create a class:
public class AddHeadersDelegatingHandler : DelegatingHandler
{
public AddHeadersDelegatingHandler() : base(new HttpClientHandler())
{
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Headers.Add("X-MyTestHeader", "MyValue"); // Add whatever headers you want here
return base.SendAsync(request, cancellationToken);
}
}
Then just change your existing registration:
builder.Services.AddScoped(sp => new HttpClient
{
BaseAddress = new Uri("https://localhost:7280/")
});
To:
builder.Services.AddScoped(sp => new HttpClient(new AddHeadersDelegatingHandler())
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});
The interesting points to note:
- Do provide a constructor to your
DelegatingHandler
and pass to the base constructor a new instance ofHttpClientHandler
. If you miss this step you'll get a runtime error that the delegating handler hasn't been assigned a target. SendAsync
can be an async method. In this particular case, since it doesn't await anything, it's not.- You could continue to use
new Uri("https://localhost:7280/")
butbuilder.HostEnvironment.BaseAddress
is usually preferred. - Naturally to do anything with the response, you should make the method async, await
base.SendAsync
, which provides you with the response, and do what you will with it.