在HttpStatusCode.Unauthorized之后使用Polly重试

Vin*_*mth 9 c# asp.net-mvc polly

我正在调用外部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;
    }
Run Code Online (Sandbox Code Playgroud)

我在ExecuteAsync语句中添加了断点,并且DoSomethingAsync- 当我跳过时ExecuteAsync DoSomethingAsync没有调用并且控制返回到调用的函数MakeGetRequestAsync

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

我已经看过关于Stack Overflow的Polly文档和Polly问题,但我无法弄清楚发生了什么......

mou*_*ler 6

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

如果您的实际代码与上面的代码示例完全相同,.ExecuteAsync(...)则会导致.Retry(...)[同步​​策略]和.ExecuteAsync(...)[异步执行] 之间的不匹配.由于抛出此异常,CallApiAsync()确实从未调用过.调用时,您应该能够看到抛出的异常MakeGetRequestAsync()

整体代码方法看起来很好:这个重试 - 刷新 - 身份验证是与Polly一起经过验证的模式!


Yus*_*ali 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);
Run Code Online (Sandbox Code Playgroud)

FooRefreshAuthorizationAsync(...)方法可以获取新的授权令牌并将其传递给使用Polly.Context.