我正在调用外部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
的函数1}}
我不明白为什么DoSomethingAsync
没有被召唤 - 任何人都可以帮助我实现我想要实现的目标吗?
我看过Polly文档&amp;关于Stack Overflow的Polly问题,但我无法弄清楚发生了什么......
答案 0 :(得分:6)
要使用ExecuteAsync()
,您必须将政策声明为.RetryAsync(...)
,而不是.Retry(...)
。
如果您的实际代码与上面的代码示例完全相同,则.ExecuteAsync(...)
会因.Retry(...)
[同步策略]与.ExecuteAsync(...)
[异步执行]之间的不匹配而失败。由于抛出此异常,因此确实从未调用CallApiAsync()
。在调用MakeGetRequestAsync()
总体代码方法看起来很好:此重试 - 刷新 - 身份验证是proven pattern with Polly!
答案 1 :(得分:2)
我要回答这个老问题只是为了指出正式记录了该模式的Polly Wiki页面:
retry-to-refresh-authorization
尤其是以下建议的代码段:
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
通过策略执行的委托。
答案 2 :(得分:1)
这就是异步等待在.net中工作的方式,当代码执行到this.
时,会发生两件事
代码的当前线程应该释放以使您的代码异步,这意味着,您的方法应该返回
当你等待的任务完成后,你的方法应该从以前的地方继续