PoliNorError.Extensions.Http 0.9.0

There is a newer version of this package available.
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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PoliNorError.Extensions.Http" Version="0.9.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PoliNorError.Extensions.Http" Version="0.9.0" />
                    
Directory.Packages.props
<PackageReference Include="PoliNorError.Extensions.Http" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PoliNorError.Extensions.Http --version 0.9.0
                    
#r "nuget: PoliNorError.Extensions.Http, 0.9.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PoliNorError.Extensions.Http@0.9.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PoliNorError.Extensions.Http&version=0.9.0
                    
Install as a Cake Addin
#tool nuget:?package=PoliNorError.Extensions.Http&version=0.9.0
                    
Install as a Cake Tool

The library provides an outgoing request resiliency pipeline for HttpClient, using policies from the PoliNorError library.

⚑ Key Features

  • Explicit resiliency pipeline based on DelegatingHandlers

  • Flexible 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
  • .NET Standard 2.0 compatible

πŸ”‘ Key Concepts

  • 🟦 Resiliency pipeline - the pipeline of DelegatingHandler, using policies from the PoliNorError library.
  • ➑ 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

  1. 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.

  1. Use the library's IHttpClientBuilder.WithResiliencePipeline extension method to build a pipeline of DelegatingHandlers. Within this scope, configure a handler to use a policy via the AddPolicyHandler method:
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 - Func that uses the IServiceProvider to create a policy.
  • funcThatUsesContextAndServiceProviderToCreatePolicy - Func that uses the IServiceProvider and context to create a policy.
  1. Complete the pipeline by calling AsFinalHandler on the last handler and configuring HttpErrorFilter to 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>()
		...

  1. Wrap HttpClient calls in a catch block for HttpPolicyResultException. For unsuccessful requests, inspect the properties of HttpPolicyResultException to 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 an HttpRequestException, the InnerException will be that HttpRequestException.
    • Otherwise, the exception originates from one of the handlers, either inside or outside the resiliency pipeline.
  • FailedResponseData - not null if the status code part of the handling filter matches the response status code.
  • HasFailedResponse - true if FailedResponseData is not null.
  • PolicyResult - specifies the PolicyResult<HttpResponseMessage> result that is produced by a policy that belongs to the DelegatingHandler that throws this exception.
  • InnermostPolicyResult - specifies the PolicyResult<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 HttpClient via WithResiliencePipeline

  • First-class support for typed and named HttpClient

  • You 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.
  • 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.9.1 31 1/22/2026
0.9.0 31 1/22/2026
0.8.0 194 10/20/2025
0.5.0 192 8/10/2025
0.3.0 203 6/15/2025
0.2.0 241 4/22/2025
0.1.1 214 3/12/2025
0.1.0 205 3/12/2025