15

我正在调用外部 API,并希望处理调用返回Unauthorized HttpResponseMessage. 发生这种情况时,我想刷新访问令牌并再次拨打电话。

我正在尝试使用Polly以下代码:

    public async Task<HttpResponseMessage> MakeGetRequestAsync()
    {
        var retryPolicy = Policy
            .HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Unauthorized)
            .Retry(1, (exception, retryCount) =>
            {
                RefreshAccessToken();
            });

        var result = await retryPolicy.ExecuteAsync(() => CallApiAsync());

        return result;
    }


    private async Task<HttpResponseMessage> CallApiAsync()
    {
        var url = Options.ResourceSandboxUrl;

        var httpClient = new HttpClient();
        SetRequestHeaders(httpClient);
        var response = await httpClient.GetAsync(url);

        response.StatusCode = HttpStatusCode.Unauthorized;
        return response;
    }

ExecuteAsync我在语句上设置了断点,并且在DoSomethingAsync- 当我跨过时ExecuteAsync DoSomethingAsync不调用并且控制权返回给调用的函数MakeGetRequestAsync

我不明白为什么DoSomethingAsync不叫 - 任何人都可以帮助我实现我想要实现的目标吗?

我查看了有关 Stack Overflow 的 Polly 文档和 Polly 问题,但我不知道发生了什么......

4

3 回答 3

9

要使用ExecuteAsync(),您必须将策略声明为.RetryAsync(...),而不是.Retry(...)

如果您的实际代码与上面的代码示例完全相同,则将引发[a sync policy] 和[an async execution].ExecuteAsync(...)之间的不匹配。由于抛出了此异常,因此确实从未调用过。调用时,您应该能够看到抛出的异常.Retry(...).ExecuteAsync(...)CallApiAsync()MakeGetRequestAsync()

整体代码方法看起来不错:这种重试刷新身份验证是Polly 的一种经过验证的模式

于 2017-01-28T15:41:45.017 回答
5

我回答这个老问题只是为了指出官方记录了这种模式的 Polly wiki 页面:

重试刷新授权

特别是这是建议的代码片段:

var authorisationEnsuringPolicy = Policy
    .HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Unauthorized) 
    .RetryAsync(
       retryCount: 1, // Consider how many retries. If auth lapses and you have valid credentials, one should be enough; too many tries can cause some auth systems to blacklist. 
       onRetryAsync: async (outcome, retryNumber, context) => FooRefreshAuthorizationAsync(context), 
      /* more configuration */); 

var response = authorisationEnsuringPolicy.ExecuteAsync(context => DoSomethingThatRequiresAuthorization(context), cancellationToken);

FooRefreshAuthorizationAsync(...)方法可以获取一个新的授权令牌,并将其传递给通过策略执行的委托,使用Polly.Context.

于 2020-06-14T15:03:11.887 回答
0

这就是 .net 中 async await 的工作方式,当你的代码执行到 a 时await,会发生两件事

  1. 您的代码的当前线程应该释放以使您的代码异步,这意味着您的方法应该返回

  2. 当您等待的任务完成时,您的方法应该从以前的位置继续

于 2017-01-28T13:22:51.770 回答