大佬教程收集整理的这篇文章主要介绍了将范围服务注入 DelegatingHandler 抛出 InvalidOperationException,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在重构我的代码以使用 Refit 调用 WebAPI 服务。接口已设置,我还创建了一个委托处理程序:
public class AuthHandler : DelegaTingHandler
{
private Readonly TokenProvIDer tokenProvIDer;
private Readonly ISessionStorageservice sessionStorage;
public AuthHandler (
TokenProvIDer tokenProvIDer,ISessionStorageservice sessionStoragE)
{
this.tokenProvIDer = tokenProvIDer ?? throw new ArgumentNullException(nameof(tokenProvIDer));
this.sessionStorage = sessionStorage ?? throw new ArgumentNullException(nameof(sessionStoragE));
}
protected overrIDe async Task<httpResponsemessage> SendAsync(httprequestmessage request,CancellationToken ct)
{
var sometoken = await sessionStorage.GetItemAsync<String>("sometoken");
request.headers.Authorization = new AuthenticationheaderValue("Bearer",tokenProvIDer.Accesstoken);
request.headers.Add("sometoken",sometoken);
return await base.SendAsync(request,ct).ConfigureAwait(false);
}
}
在Startup.cs
中:
services.AddblazoredSessionStorage();
services.AddScoped<TokenProvIDer>();
services.AddScoped<AuthHandler>();
services.AddRefitClIEnt<IAPIservice>().ConfigurehttpClIEnt(options =>
{
options.baseAddress = new Uri(Configuration["Server:Url"]);
options.Defaultrequestheaders.Accept.Add(new MediaTypeWithQualityheaderValue("application/Json"));
}).AddhttpmessageHandler<AuthHandler>();
我有一个 razor 组件,我想使用上面的服务,所以我注入了这些服务并做到了:
@code {
protected overrIDe async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var List = await myservice.GetListAsync();
}
}
}
此外,在 _Host.csHTML
中:
<environment include="Staging,Production">
<component render-mode="ServerPrerendered" type="typeof(App)" param-InitialState="tokens" />
</environment>
<environment include="Development">
<component render-mode="Server" type="typeof(App)" param-InitialState="tokens" />
</environment>
但是我得到以下异常:
system.invalIdoperationException:此时无法发出 JavaScript 互操作调用。这是因为组件是静态呈现的。启用预渲染后,只能在 OnAfterRenderAsync 生命周期方法期间执行 JavaScript 互操作调用。
所以,为了确定我是否有值,我在调用 API 之前添加了以下内容:
var sometoken = await sessionStorage.GetItemAsync<String>("sometoken");
var accesstoken = tokenProvIDer.Accesstoken;
而且我确实在两个变量中都有值。
那么为什么我不能从委托处理程序访问会话存储?为什么令牌提供程序实例被实例化,但属性全为空(也在处理程序中)?
编辑
我只需要一个地方来存放我的令牌。不管是令牌提供者还是会话存储,只要它适用于 blazor 页面/组件和其他服务。
更新 1
可以跳过 DI 并像这样创建服务:
var service = Restservice.For<IMyservice>(new httpClIEnt(new AuthHandler(tokenProvIDer,sessionStoragE))
{
BaseAddress = new Uri(myUrl)
}
);
这将按预期工作。但是,使用 DI 会好得多。问题可能出在 Blazor 或 Refit 中。
我想我已经找到了解决问题的可行方法。
我没有依赖 Refit 使用的 httpClientFactory
,而是创建了自己的 DI 逻辑。
上一个:
Uri apiBaseUri = dataAccessLayerConfiguration.API.baseUrl;
foreach (Type repositoryType in repositoryTypes)
{
services
.AddRefitClient(repositoryTypE)
.ConfigurehttpClient((httpClient) => httpClient.baseAddress = apiBaseUri)
.AddhttpmessageHandler<requestHeaderHandler>();
}
当前:
foreach (Type repositoryType in repositoryTypes)
{
services.AddTransient(
repositoryType,(provider) =>
{
return
RepositoryFactory.Create(
repositoryType,configuration,provider.Getrequiredservice<ITokenCacheProvider>(),() => provider.Getrequiredservice<ICurrentUser>());
});
}
我使用的 RepositoryFactory 为每个 API 接口创建了 httpClients:
return
Restservice.For<TRepository>(
new httpClient(
new requestHeaderHandler(tokenCacheProvider,fetchCurrentUserDelegatE)
{
InnerHandler = new httpClientHandler()
},truE)
{
BaseAddress = configuration.DataAccessLayer.API.baseUrl
});
我目前在 OnParametersSet()
方法的布局代码中获取当前用户。我对它还不完全满意,但现在对我来说已经足够了。但是,重要的是在创建 httpClient 时不要直接注入用户对象,而只注入一个委托(或 Func<>
),然后在需要时解析用户对象。
通过这种方式,我能够解决 Refit/httpClientFactory 的范围问题,但仍然继续使用依赖注入。它可能不是对每个人来说都是 100% 的解决方案,但足以为您自己的项目找到正确的方向。
以上是大佬教程为你收集整理的将范围服务注入 DelegatingHandler 抛出 InvalidOperationException全部内容,希望文章能够帮你解决将范围服务注入 DelegatingHandler 抛出 InvalidOperationException所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。