程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了将范围服务注入 DelegatingHandler 抛出 InvalidOperationException大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决将范围服务注入 DelegaTingHandler 抛出 InvalidoperationException?

开发过程中遇到将范围服务注入 DelegaTingHandler 抛出 InvalidoperationException的问题如何解决?下面主要结合日常开发的经验,给出你关于将范围服务注入 DelegaTingHandler 抛出 InvalidoperationException的解决方法建议,希望对你解决将范围服务注入 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,请注明来意。