简体   繁体   中英

ASP.NET Core Web API - JWT Message Handler - No Registered Type Error

I have created a JWT Token Handler for my Web API project. The idea is that this API is merely a gateway to other APIs and a token is shared across them all. So when a call is made to my API and I am forwarding the call to another, I want to automatically forward the JWT that was attached to the initial request.

I made a custom MessageHandler as seen below:

public class JwtTokenHeaderHandler : DelegatingHandler
{
    private readonly HttpContext httpContext;
   public JwtTokenHeaderHandler(HttpContext httpContext)
   {
       this.httpContext = httpContext;
   }
   protected override async Task<HttpResponseMessage> SendAsync(
       HttpRequestMessage request,
       CancellationToken cancellationToken)
   {
       string savedToken = await this.httpContext.GetTokenAsync("access_token");
       request.Headers.Add("bearer", savedToken);
       return await base.SendAsync(request, cancellationToken);
   } 
}

Then I registered it as a service in the Startup as below:

services.AddTransient<HttpMessageHandler>(p => p.GetRequiredService<JwtTokenHeaderHandler>());

IHttpClientBuilder serviceClientBuilder = services.AddHttpClient<IService, Service>(client =>
{
    client.BaseAddress = new Uri(this.Configuration.GetValue<string>("ServiceURL"));
}).AddHttpMessageHandler<JwtTokenHeaderHandler>();

The application runs up until a request is made and then this exception comes up:

An unhandled exception has occurred while executing the request.

System.InvalidOperationException: No service for type 'Application.API1.JwtTokenHeaderHandler' has been registered. at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.<>c__4`1.b__4_1(HttpMessageHandlerBuilder b) at Microsoft.Extensions.Http.DefaultHttpClientFactory.<>c__DisplayClass17_0.g__Configure|0(HttpMessageHandlerBuilder b) at Microsoft.Extensions.Http.LoggingHttpMessageHandlerBuilderFilter.<>c__DisplayClass3_0.b__0(HttpMessageHandlerBuilder builder)

First, injecting HttpContext directly will cause issues. Use IHttpContextAccessor and access the context in the Send method.

public class JwtTokenHeaderHandler : DelegatingHandler {
    private readonly IHttpContextAccessor accessor;

    public JwtTokenHeaderHandler(IHttpContextAccessor accessor) {
        this.accessor = accessor;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
        string savedToken = await accessor.HttpContext.GetTokenAsync("access_token");
        request.Headers.Add("bearer", savedToken);
        return await base.SendAsync(request, cancellationToken);
    } 
}

Next GetRequiredService throws that exception when the requested service is not registered with the collection so make sure to register the handler with the container

Note

The handler type must be registered as a transient service.

Reference AddHttpMessageHandler<THandler>(IHttpClientBuilder)

services.AddTransient<JwtTokenHeaderHandler>();

So that JwtTokenHeaderHandler can be resolved when requested from the service provider

services.AddTransient<HttpMessageHandler>(p => p.GetRequiredService<JwtTokenHeaderHandler>());
services.AddHttpClient<IService, Service>(client => {
    client.BaseAddress = new Uri(this.Configuration.GetValue<string>("ServiceURL"));
}).AddHttpMessageHandler<JwtTokenHeaderHandler>();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM