Home > Software engineering >  Blazor WebAssembly Add headers to all API requests
Blazor WebAssembly Add headers to all API requests

Time:06-23

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 of HttpClientHandler. 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/") but builder.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.
  • Related