gpt4 book ai didi

c# - 范围服务为请求创建两个不同的实例

转载 作者:行者123 更新时间:2023-12-05 04:25:54 24 4
gpt4 key购买 nike

我是 Asp.Net core 6 的新手,正在研究在请求中接收不记名 token 的 GraphQL API。然后 API 调用另一个 Web API 并在 header 中传递相同的不记名 token 。下面是我的代码的样子-

程序.cs:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<HeaderHandler>();
builder.Services.AddScoped<TokenContainer>();
//builder.Services.AddScoped<IFooGateway, FooGateway>();

builder.Services.AddHttpClient<IFooGateway, FooGateway>((c) =>
{
c.BaseAddress = new Uri(builder.Configuration["FooApiUrl"]);
})
.AddHttpMessageHandler<HeaderHandler>();

builder.Services.AddTransient<GraphApiService>();

var app = builder.Build();
app.UseMiddleware<HeaderMiddleware>();
app.MapGraphQL();
app.Run();

HeaderMiddleware.cs

public class HeaderMiddleware
{
//TokenContainer _tokenContainer;

private readonly RequestDelegate _requestDelegate;
public HeaderMiddleware()
{
}
public HeaderMiddleware(RequestDelegate requestDelegate)
{
_requestDelegate = requestDelegate;
//_tokenContainer = tokenContainer;
}

public async Task InvokeAsync(HttpContext context, TokenContainer tokenContainer)
{
var header = context.Request.Headers.Authorization;
tokenContainer.SetToken(header);
await _requestDelegate(context);
}

token 容器.cs:

public class TokenContainer
{
public string BearerToken { get; private set; }

public void SetToken(string token) => BearerToken = token;
}

HeaderHandler.cs:

public class HeaderHandler : DelegatingHandler
{
TokenContainer _tokenContainer;
public HeaderHandler()
{

}

public HeaderHandler(TokenContainer tokenContainer)
{
_tokenContainer = tokenContainer;
}

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// for every request sent via the http client, intercept & add the bearer token header.
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", _tokenContainer.BearerToken);
// continue with request pipeline
return await base.SendAsync(request, cancellationToken);
}
}

FooGateway.cs:

public class FooGateway : IFooGateway
{
private readonly HttpClient _httpClient;
private readonly IConfiguration _configuration;
private readonly string _context = String.Empty;

public FooGateway(HttpClient httpClient, IConfiguration configuration)
{
_configuration = configuration;
_context = configuration["FooContext"];
_httpClient = httpClient;
}
public void DoSomething()
{
_httpClient.PostAsync("/blabla");
}

}

因此,我们的想法是,每个传入请求的承载 token 都将存储在一个名为 TokenContainer 的类中,HttpHandler 会将其添加到所有传出请求中。但是,发生的情况是 token 存储在 TokenContainer 中,但 HeaderHandler 在其构造函数中获得了 TokenContainer 的不同实例,其 BearerToken 属性设置为 null。有人可以解释为什么中间件中的相同 TokenContainer 实例没有传递到 HeaderHandler 中吗?

最佳答案

您看到的问题是因为 HttpMessageHandler 的生命周期与请求的生命周期相同:通常,同一个处理程序将在许多请求中重复使用,并在到期时单独控制定时器等。

您不应期望注入(inject)到您的消息处理程序中的服务与注册为作用域时在其外部注入(inject)的对象相同。

https://andrewlock.net/understanding-scopes-with-ihttpclientfactory-message-handlers/#scope-duration-in-ihttpclientfactory

正如文章所建议的,要使用与处理程序外部相同的作用域实例,您必须依赖 IHttpContextAccessor 来访问当前的 HttpContext 并获取服务从那里。所以你的处理程序实现看起来像这样:

public class HeaderHandler : DelegatingHandler
{
IHttpContextAccessor _httpContextAccessor;
public HeaderHandler()
{

}

public HeaderHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var tokenContainer = _httpContextAccessor
.HttpContext
.RequestServices
.GetRequiredService<TokenContainer>();


// for every request sent via the http client, intercept & add the bearer token header.
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", tokenContainer.BearerToken);
// continue with request pipeline
return await base.SendAsync(request, cancellationToken);
}
}

这应该确保 TokenContainer 实例在您当前的请求和 http 调用中是相同的。

请记住,要添加此功能,您需要像这样添加访问器:

services.AddHttpContextAccessor();

关于c# - 范围服务为请求创建两个不同的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73152550/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com