asp.net-core.net-corepollydotnet-aspire

Override default Polly/resilience policy set in ASP.NET Aspire


I have an ASP.NET Aspire application which registers default resillience

builder.Services.ConfigureHttpClientDefaults(http =>
{
    // Turn on resilience by default
    http.AddStandardResilienceHandler();

    // Turn on service discovery by default
    http.AddServiceDiscovery();
});

Which is all fine and good good and I don't want to remove it.

But for a specific typed client, I want to disable these policies and use my own policies.

builder.Services.AddHttpClient<MyService>(client =>
{
    client.BaseAddress = new Uri("http://example.com", UriKind.Absolute);
})
.AddPolicyHandler(Policy<HttpResponseMessage>
    .Handle<HttpRequestException>()
    .OrResult(msg => msg.StatusCode == HttpStatusCode.BadGateway
                    || msg.StatusCode == HttpStatusCode.ServiceUnavailable
                    || msg.StatusCode == HttpStatusCode.GatewayTimeout)
    .CircuitBreakerAsync(5, TimeSpan.FromSeconds(15))
);

But its not working, the default policy still applies (which has timeout policy of 10 seconds). I can't find any way to disable it, as there's no .ClearPolicies() method or similar.

Any way to do this, without removing the defaults?


Solution

  • Seems you are not the first person to encounter this issue. I can see they tried to get an API into .NET 9 called RemoveAllResilienceHandlers but that was marked experimental and looks to have been removed in .NET 10. However, this discussion also has a fix you can use:

    public static class HttpClientBuilderExtensions
    {
        /// <summary>
        /// Remove already configured resilience handlers
        /// </summary>
        /// <param name="builder">The builder instance.</param>
        /// <returns>The value of <paramref name="builder" />.</returns>
        public static IHttpClientBuilder ClearResilienceHandlers(
            this IHttpClientBuilder builder)
        {
            builder.ConfigureAdditionalHttpMessageHandlers(static (handlers, _) =>
            {
                for (int i = 0; i < handlers.Count;)
                {
                    if (handlers[i] is ResilienceHandler)
                    {
                        handlers.RemoveAt(i);
                        continue;
                    }
                    i++;
                }
            });
            return builder;
        }
    }
    

    And now you can do something like this:

    builder.Services
        .AddHttpClient<MyService>(...)
        .ClearResilienceHandlers()
        .AddPolicyHandler(...);