You're configuring a policy to guard the HttpClient GetAsync method, which returns Task<HttpResponseMessage>
. You want to configure a Policy<HttpResponseMessage>
to work with this method, using async handlers.
Policy<T>.HandleResult(Func<T, bool> filter)
allows you to look at the HttpResponseMessage and determine whether you want to handle that result.
A couple of options. One, you could figure out deserializing/reading the HttpResponseMessage's json payload within the HandleResult method. You only get a Func<HttpResponseMessage, bool>
to work with. This would need to happen synchronously, as adding async/await changes the return type to Task.
Second, you could apply the policy at a higher level. Get the response as you are httpclient.GetAsync(uri), then deserialize the content. Maybe have one Policy<HttpResponseMessage>
wrap the httpclient call, and one Policy<MyAbstractApiResponse>
to look for the custom error code after deserializing?
As a note, an API error should really be picked up by the IsSuccessStatusCode property on the HttpResponseMessage. Your REST api (is it yours? that's an assumption) should be setting status codes appropriate to the error, not solely 200's and custom response properties.
Related further reading: Check string content of response before retrying with Polly
Update:
class Consumer
{
public void Test()
{
var apiResponse = Policy<IApiResponse>
.HandleResult(resp => !string.IsNullOrWhiteSpace(resp.ErrorCode))
// Setup Policy
.ExecuteAsync(() => otherClassInstance.MakeApiCall());
}
}
class OtherClass
{
HttpClient httpClient = ...;
public async Task<IApiResponse> MakeApiCall()
{
var response = Policy<HttpResponseMessage>
.HandleResult(message => !message.IsSuccessStatusCode)
// Setup Policy
.ExecuteAsync(() => httpClient.GetAsync(url));
var content = await response.ReadAsStringAsync();
return new ApiResponse(content);
}
}
I didn't look at real method names or syntax in putting that together so it might not compile. Hopefully you get the idea I'm trying to convey, one policy is called from within another.