PoliNorError.Extensions.Http
0.9.0
See the version list below for details.
dotnet add package PoliNorError.Extensions.Http --version 0.9.0
NuGet\Install-Package PoliNorError.Extensions.Http -Version 0.9.0
<PackageReference Include="PoliNorError.Extensions.Http" Version="0.9.0" />
<PackageVersion Include="PoliNorError.Extensions.Http" Version="0.9.0" />
<PackageReference Include="PoliNorError.Extensions.Http" />
paket add PoliNorError.Extensions.Http --version 0.9.0
#r "nuget: PoliNorError.Extensions.Http, 0.9.0"
#:package PoliNorError.Extensions.Http@0.9.0
#addin nuget:?package=PoliNorError.Extensions.Http&version=0.9.0
#tool nuget:?package=PoliNorError.Extensions.Http&version=0.9.0
The library provides an outgoing request resiliency pipeline for HttpClient, using policies from the PoliNorError library.
β‘ Key Features
Explicit resiliency pipeline based on
DelegatingHandlersFlexible policy creation
- Inline policies
- Policies resolved from
IServiceProvider - Context-aware policy creation
Powerful final-handler failure filtering Precisely control which HTTP responses and exceptions should be treated as failures:
- Transient HTTP errors (5xx, 408, 429)
HttpRequestException- Custom status codes or status code categories
Full exception transparency Failures are surfaced via a single, rich exception:
HttpPolicyResultException, preserving:- The original exception
- HTTP response details
- Policy execution results
Control exception flow between handlers using
IncludeException<TException>Deep PoliNorError integration Use PoliNorError's fluent APIs for:
- Retry, fallback, and custom policies
- Exception filtering and processing
- Policy result inspection and logging
Works with
- Typed and named
HttpClient IHttpClientFactory
- Typed and named
.NET Standard 2.0 compatible
π Key Concepts
- π¦ Resiliency pipeline - the pipeline of
DelegatingHandler, using policies from thePoliNorErrorlibrary. - β‘ OuterHandler is the first handler in the pipeline (closest to the request initiator).
- β¬ InnerHandler is the next handler in the pipeline (closer to the final destination).
- π΅ FinalHandler is the innermost handler in the pipeline.
- β Transient HTTP errors are temporary failures that occur when making HTTP requests (HTTP 5xx, HTTP 408, HTTP 429 and
HttpRequestException).
π Usage
- Configure typed or named
HttpClient:
services.AddHttpClient<IAskCatService, AskCatService>((sp, config) =>
{
...
config.BaseAddress = new Uri(settings.BaseUri);
...
})...
, where AskCatService is a service that implements IAskCatService, with HttpClient or IHttpClientFactory injected.
- Use the library's
IHttpClientBuilder.WithResiliencePipelineextension method to build a pipeline ofDelegatingHandlers. Within this scope, configure a handler to use a policy via theAddPolicyHandlermethod:
services.AddHttpClient<IAskCatService, AskCatService>((spForClient, client) =>
{
...
})
.WithResiliencePipeline((pb) =>
pb
.AddPolicyHandler(PolicyJustCreated)
.AddPolicyHandler((IServiceProvider sp) => funcThatUsesServiceProviderToCreatePolicy(sp))
...
)
Or use the WithResiliencePipeline method overload that includes an additional context parameter:
services.AddHttpClient<IAskCatService, AskCatService>((spForClient, client) =>
{
...
})
.WithResiliencePipeline<SomeContextType>((pb) =>
pb
.AddPolicyHandler((SomeContextType ctx, IServiceProvider sp) =>
funcThatUsesContextAndServiceProviderToCreatePolicy(ctx, sp))
.AddPolicyHandler((IServiceProvider sp) => funcThatUsesServiceProviderToCreatePolicy(sp))
...
, context)
, where
pb- represents the pipeline builder.PolicyJustCreated- a policy from the PoliNorError library.funcThatUsesServiceProviderToCreatePolicy-Functhat uses theIServiceProviderto create a policy.funcThatUsesContextAndServiceProviderToCreatePolicy-Functhat uses theIServiceProviderand context to create a policy.
- Complete the pipeline by calling
AsFinalHandleron the last handler and configuringHttpErrorFilterto filter transient HTTP errors,
services.AddHttpClient<IAskCatService, AskCatService>((sp, config) =>
{
...
})
.WithResiliencePipeline((pb) =>
pb
...
.AddPolicyHandler(PolicyForFinalHandler)
//Adds transient http errors to the response handling filter.
.AsFinalHandler(HttpErrorFilter.HandleTransientHttpErrors())
...
)
and/or any non-successful status codes or categories
...
.AsFinalHandler(HttpErrorFilter.HandleHttpRequestException()
//Also adds 5XX status codes to the response handling filter.
.OrServerError())
...
Use IncludeException<TException> on the pipeline builder to allow an outer handler to handle only filtered exceptions from an inner handler or outside the pipeline:
...
.AsFinalHandler(HttpErrorFilter.HandleTransientHttpErrors())
//Include 'SomeExceptionFromNonPipelineHandler' exceptions in the filter
//when thrown by a non-pipeline handler (in this case).
.IncludeException<SomeExceptionFromNonPipelineHandler>()
...
- Wrap
HttpClientcalls in acatchblock forHttpPolicyResultException. For unsuccessful requests, inspect the properties ofHttpPolicyResultExceptionto access response details:
try
{
...
using var response = await _client.GetAsync(uri, token);
...
}
catch (OperationCanceledException oe)
{
...
}
catch (HttpPolicyResultException hpre)
{
//If the response status code matches the handling filter status code:
if (hpre.HasFailedResponse)
{
//For example, log a failed status code.
logger.LogError("Failed status code: {StatusCode}.", hpre.FailedResponseData.StatusCode);
}
}
catch (Exception ex)
{
...
}
π Adding Handlers Based on RetryPolicy Using the AddRetryHandler Extension Methods.
The AddRetryHandler extension methods provide a fluent way to attach a RetryPolicy to an HTTP message handler pipeline.
One of these methods allows adding a handler via RetryPolicyOptions and is responsible for setting up RetryPolicy details, including:
- Error processing,
- Policy result handling,
- Error filters,
- Policy naming,
- Delay between retries,
- And ultimately registering the policy with
AddPolicyHandler.
Example: Retry with logging, filtering, and delay:
var retryOptions = new RetryPolicyOptions()
{
PolicyName = "MyRetryPolicy",
ConfigureErrorProcessing = (bp) =>
bp.WithErrorProcessorOf(
(Exception ex, ProcessingErrorInfo pi) =>
loggerTest.LogError(
ex,
"Exception on attempt { Attempt }:",
pi.GetRetryCount() + 1)),
ConfigureErrorFilter = (f) => f.ExcludeError<SomeException>(),
ConfigurePolicyResultHandling = (handlers) => handlers.AddHandler(
(pr, _) =>
{
if (pr.IsFailed)
{
loggerTest.LogWarning(
"{Errors} exceptions were thrown during handling by {PolicyName}.",
pr.Errors.Count(),
pr.PolicyName);
}
}
),
RetryDelay = ConstantRetryDelay.Create(TimeSpan.FromSeconds(1))
};
This example configures RetryPolicyOptions with:
- A policy name ("MyRetryPolicy"),
- An error processor (logs exceptions with attempt numbers),
- An error filter (excludes
SomeException), - A result handler (logs warnings about exception counts),
- A 1-second constant delay between retries.
Attach a retry handler to the pipeline using these options:
services.AddHttpClient<IAskCatService, AskCatService>((sp, config) =>
{
...
})
.WithResiliencePipeline((pb) =>
pb
...
//Maximum number of retries: 3
.AddRetryHandler(3, retryOptions)
.AsFinalHandler(HttpErrorFilter.HandleTransientHttpErrors())
...
)
You can also configure RetryPolicy details inline using the AddRetryHandler overload that accepts an Action<RetryPolicyOptions>.
π HttpPolicyResultException properties
Public properties of the HttpPolicyResultException:
InnerException- If the response status code matches the handling filterβs status code, it will be a special
FailedHttpResponseException. - If no handlers inside or outside the resiliency pipeline throw an exception, and the
HttpClientβs primary handler throws anHttpRequestException, theInnerExceptionwill be thatHttpRequestException. - Otherwise, the exception originates from one of the handlers, either inside or outside the resiliency pipeline.
- If the response status code matches the handling filterβs status code, it will be a special
FailedResponseData- not null if the status code part of the handling filter matches the response status code.HasFailedResponse- true ifFailedResponseDatais not null.PolicyResult- specifies thePolicyResult<HttpResponseMessage>result that is produced by a policy that belongs to theDelegatingHandlerthat throws this exception.InnermostPolicyResult- specifies thePolicyResult<HttpResponseMessage>result produced by a policy of the final handler or by a handler in the pipeline that throws its own exception.IsErrorExpected- indicates whether the filter for the original exception was satisfied.IsCanceled- indicates whether the execution was canceled.
β Why PoliNorError.Extensions.Http?
Declarative pipeline builder for
HttpClientviaWithResiliencePipelineFirst-class support for typed and named
HttpClientYou decide what a failure is
- Filter transient HTTP errors in the flexible final handler and control exception flow between handlers.
One clear failure signal
- All handled failures surface as a single, information-rich
HttpPolicyResultException.
- All handled failures surface as a single, information-rich
Helpers to add handlers with rich configuration (
AddRetryHandler,AddFallbackHandler)First-class PoliNorError integration
- Advanced error processing, contextual logging, and policy result inspection.
Samples
See the samples folder for concrete examples.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Extensions.Http (>= 10.0.2)
- PoliNorError (>= 2.24.20)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.