Table of Contents

Class HttpRestClient

Namespace
Kampute.HttpClient
Assembly
Kampute.HttpClient.dll

Facilitates HTTP communication with RESTful APIs by wrapping HttpClient.

public class HttpRestClient : IDisposable
Inheritance
HttpRestClient
Implements
Inherited Members
Extension Methods

Remarks

HttpRestClient abstracts the complexities of HttpClient, supporting the sharing of a single HttpClient instance across multiple HttpRestClient instances. This optimizes resource use and connection management, enhancing performance by reusing HTTP connections, especially during concurrent access to various services or API endpoints.

The client allows for scoped request headers and properties, providing temporary configurations that do not alter global settings. This ensures that changes remain isolated to specific contexts, increasing maintainability and reducing configuration errors during runtime.

It includes a ResponseDeserializers collection that automatically deserializes HTTP response content into .NET objects based on the response's Content-Type. If the Accept header is not predefined, the client dynamically adjusts it based on the configured response deserializers and the expected .NET object type.

Transient failures and network interruptions are managed via the BackoffStrategy property, which outlines retry logic and wait times between retries. This strategic approach helps avoid server overloads and improves communication success without excessive resource use.

Extensible error handling is enabled through the ErrorHandlers collection, allowing custom IHttpErrorHandler implementations to handle specific HTTP errors with tailored strategies.

Lifecycle events like BeforeSendingRequest and AfterReceivingResponse enhance request and response handling by enabling modifications, inspections, and logging, allowing for a highly customizable interaction.

Constructors

HttpRestClient()

Initializes a new instance of the HttpRestClient class.

public HttpRestClient()

Remarks

This constructor initializes the HttpRestClient using a shared HttpClient instance acquired from the SharedHttpClient static class.

HttpRestClient(Reference)

Initializes a new instance of the HttpRestClient class with the specified shared HttpClient reference.

public HttpRestClient(SharedDisposable<HttpClient>.Reference httpClientReference)

Parameters

httpClientReference SharedDisposable<HttpClient>.Reference

A reference to a shared HttpClient instance, managed as SharedDisposable<T>.Reference.

Remarks

This constructor takes ownership of the shared HttpClient reference and ensures it is properly released when the HttpRestClient is disposed.

Exceptions

ArgumentNullException

Thrown if httpClientReference is null>.

HttpRestClient(HttpClient, bool)

Initializes a new instance of the HttpRestClient class with the specified HttpClient.

public HttpRestClient(HttpClient httpClient, bool disposeClient = true)

Parameters

httpClient HttpClient

The HttpClient to be used by the HttpRestClient.

disposeClient bool

Specifies whether the HttpRestClient should dispose of the provided HttpClient when the HttpRestClient is disposed.

Exceptions

ArgumentNullException

Thrown if httpClient is null.

Properties

BackoffStrategy

Gets or sets the backoff strategy for handling transient connection failures during HTTP requests.

public IHttpBackoffProvider BackoffStrategy { get; set; }

Property Value

IHttpBackoffProvider

The backoff strategy for handling transient connection failures during HTTP requests.

Remarks

This property specifies the retry logic applied exclusively to connection failures, not to the processing of server responses. It determines if and when the client should retry a failed connection attempt before giving up. This approach is crucial for dealing with transient network issues or temporary server unavailability. The default is None.

BaseAddress

Gets or sets the base address for HTTP requests.

public Uri? BaseAddress { get; set; }

Property Value

Uri

The base address for HTTP requests.

Remarks

If the provided base address does not end with a slash, one is automatically appended. The presence or absence of this trailing slash is significant in how relative URLs are resolved. For instance, if the base address is http://example.com/api (no trailing slash) and the relative URL is "users", the resolved URL will be http://example.com/users. Conversely, if the base address ends with a slash, like http://example.com/api/, the resolved URL will be http://example.com/api/users. This subtle difference can be crucial in ensuring requests are routed correctly.

It's also worth noting that a null value for the base address is acceptable and indicates that no base address is set. In such cases, any HTTP request must use an absolute URL.

DefaultRequestHeaders

Gets the headers which should be sent with each request.

public HttpRequestHeaders DefaultRequestHeaders { get; }

Property Value

HttpRequestHeaders

The headers which should be sent with each request.

ErrorHandlers

Gets the mutable collection of HTTP error handlers used for handling error responses.

public HttpErrorHandlerCollection ErrorHandlers { get; }

Property Value

HttpErrorHandlerCollection

The mutable collection of HTTP error handlers used for handling error responses.

Remarks

This property provides access to a collection of IHttpErrorHandler instances that are used to handle HTTP error responses. The handlers in this collection are tried in order to handle errors.

ResponseDeserializers

Gets the mutable collection of HTTP content deserializers used for deserializing response content.

public HttpContentDeserializerCollection ResponseDeserializers { get; }

Property Value

HttpContentDeserializerCollection

The mutable collection of HTTP content deserializers used for deserializing response content.

Remarks

This property provides access to a collection of IHttpContentDeserializer instances that are used to deserialize the content of HTTP responses. The deserializers in this list are tried in order to deserialize the response content into .NET objects.

ResponseErrorType

Gets or sets the Type used to deserialize the response body when the response status code indicates an error.

public Type? ResponseErrorType { get; set; }

Property Value

Type

The Type used to deserialize the response body when the response status code indicates an error.

Remarks

This property specifies the Type that the HttpRestClient will use to deserialize the response content in cases where the HTTP response indicates an error. It is important to ensure that the custom type specified is compatible with the expected error response format and can be deserialized by the content deserializers available to the HttpRestClient.

When the specified type implements the IHttpErrorResponse interface, the deserialized object is utilized to construct a more informative exception. This mechanism enables the integration of custom error handling strategies by leveraging structured error information returned from the server.

Methods

BeginHeaderScope(IEnumerable<KeyValuePair<string, string?>>)

Begins a new scope with the specified request headers.

public virtual IDisposable BeginHeaderScope(IEnumerable<KeyValuePair<string, string?>> headers)

Parameters

headers IEnumerable<KeyValuePair<string, string>>

The request headers to be applied exclusively during the lifetime of the new scope.

Returns

IDisposable

An IDisposable representing the new scope. Disposing of this object will end the scope and revert changes in the request headers.

Remarks

This method creates a scope associated with the current HttpRestClient instance to add, modify or remove any request header in subsequent requests during the lifetime of this scope. To remove a header, use null for its value.

Any header modifications made within this scope take precedence over the client's default headers. Header adjustments by other active scopes are overridden by those provided in this scope. However, the default request headers set on the underlying HttpClient instance take precedence over the default and scoped headers of the HttpRestClient instance because they are applied later in the message handler pipeline. To avoid conflicts, it is recommended to keep the default request headers of the underlying HttpClient instance empty.

Upon disposing of the scope, all header adjustments are reverted, restoring the headers to their state before the scope was activated.

Exceptions

ArgumentNullException

Thrown if headers is null.

BeginPropertyScope(IEnumerable<KeyValuePair<string, object?>>)

Begins a new scope with the specified request properties.

public virtual IDisposable BeginPropertyScope(IEnumerable<KeyValuePair<string, object?>> properties)

Parameters

properties IEnumerable<KeyValuePair<string, object>>

The request properties to be applied exclusively during the lifetime of the new scope.

Returns

IDisposable

An IDisposable representing the new scope. Disposing of this object will end the scope and revert changes in the request properties.

Remarks

This method creates a scope associated with the current HttpRestClient instance to add, modify or remove any request properties in subsequent requests during the lifetime of this scope. To remove a property, use null for its value.

Upon disposing of the scope, all property adjustments are reverted, restoring the properties to their state before the scope was activated.

Exceptions

ArgumentNullException

Thrown if properties is null.

CreateHttpRequest(HttpMethod, string, Type?)

Creates an HttpRequestMessage with the specified method and URI.

protected virtual HttpRequestMessage CreateHttpRequest(HttpMethod method, string uri, Type? responseObjectType)

Parameters

method HttpMethod

The HTTP method to be used for the request, such as GET, POST, PUT, etc.

uri string

The URI to which the request will be sent. Should be a valid, fully qualified URL.

responseObjectType Type

The type of the object expected to be contained in the response.

Returns

HttpRequestMessage

An HttpRequestMessage configured with the specified method and URI.

Remarks

This method constructs a new HTTP request message by setting the HTTP method and URI. It prepares the request for transmission by configuring both the headers and custom properties appropriate for the given context and operation.

Headers are added or adjusted from both the default headers provided by the DefaultRequestHeaders property and any scoped headers that are active at the time of this request’s creation. Scoped headers are prioritized over default headers in case of key conflicts to ensure that context-specific modifications are respected.

If an Accept header is absent in both default and scoped headers, it is added based on the media types supported by the content deserializers for the specified responseObjectType. If responseObjectType is null, the header defaults to accepting all media types ("*/*").

This method also includes scoped properties in the HTTP request message to provide additional context and facilitate easier tracking and processing of the request. In addition to the scoped properties, the following properties are added:

  • TransactionId A unique identifier (Guid) generated and assigned to each request, aiding in the request's tracking, debugging, and logging processes. The unique identifier ensures that each request can be individually tracked, even when multiple requests are executed simultaneously or when requests are retried due to transient failures.
  • ResponseObjectType Defines the .NET type (Type) expected in the response, if any. This metadata provides context that can improve debugging, enhance logging details, and support error recovery strategies.

Exceptions

ArgumentNullException

Thrown if method or uri is null.

DecideOnRetryAsync(HttpResponseException, HttpRequestMessage, HttpResponseMessage, CancellationToken)

Asynchronously evaluates failed HTTP responses to decide the appropriate action based on the error context and predefined error handling strategies.

protected virtual Task<HttpErrorHandlerResult> DecideOnRetryAsync(HttpResponseException error, HttpRequestMessage request, HttpResponseMessage response, CancellationToken cancellationToken)

Parameters

error HttpResponseException

The HttpResponseException encapsulating details of the encountered error during the HTTP request execution.

request HttpRequestMessage

The HttpRequestMessage that led to the failed response.

response HttpResponseMessage

The received HttpResponseMessage indicating a failure.

cancellationToken CancellationToken

A token for canceling the operation.

Returns

Task<HttpErrorHandlerResult>

A task that resolves to an HttpErrorHandlerResult, indicating whether to retry the request or that the error is unrecoverable.

Remarks

This method assesses HTTP request failures, leveraging error handling strategies within ErrorHandlers. It returns an HttpErrorHandlerResult that guides the next steps, either to retry the request with potentially modified parameters or to handle the error as unrecoverable.

Exceptions

ArgumentNullException

Thrown if error, request or response is null.

See Also

DecideOnRetryAsync(HttpRequestException, HttpRequestMessage, CancellationToken)

Asynchronously evaluates transient network issues to decide the appropriate action based on the error context and predefined error handling strategies.

protected virtual Task<HttpErrorHandlerResult> DecideOnRetryAsync(HttpRequestException error, HttpRequestMessage request, CancellationToken cancellationToken)

Parameters

error HttpRequestException

The HttpRequestException encapsulating details of the encountered error during the HTTP request execution.

request HttpRequestMessage

The HttpRequestMessage that led to the failed response.

cancellationToken CancellationToken

A token for canceling the operation.

Returns

Task<HttpErrorHandlerResult>

A task that resolves to an HttpErrorHandlerResult, indicating whether to retry the request or that the error is unrecoverable.

Remarks

This method assesses transient network issues, leveraging backoff strategies specified by BackoffStrategy. It returns an HttpErrorHandlerResult that guides the next steps, either to retry the request with potentially modified parameters or to handle the error as unrecoverable.

Exceptions

ArgumentNullException

Thrown if error or request is null.

See Also

DeserializeContentAsync(HttpResponseMessage, Type, CancellationToken)

Asynchronously deserializes the body of an HttpResponseMessage and converts it into an object of a specified type.

protected virtual Task<object?> DeserializeContentAsync(HttpResponseMessage response, Type objectType, CancellationToken cancellationToken)

Parameters

response HttpResponseMessage

The HttpResponseMessage to be read.

objectType Type

The type of object to which the response body is to be converted.

cancellationToken CancellationToken

A token for canceling the operation.

Returns

Task<object>

A task representing the asynchronous operation, with the deserialized response body as an object.

Remarks

This method uses configured content deserializers for content deserialization and supports custom content types. In case of deserialization failures, an HttpContentException is thrown, which may contain an inner exception providing more details about the parsing error.

Exceptions

ArgumentNullException

Thrown if response or objectType is null.

HttpContentException

Thrown when the response body is empty, the content type is unsupported, or parsing the response fails.

See Also

DispatchAsync(HttpRequestMessage, CancellationToken)

Asynchronously dispatches an HTTP request.

protected virtual Task<HttpResponseMessage> DispatchAsync(HttpRequestMessage request, CancellationToken cancellationToken)

Parameters

request HttpRequestMessage

The HttpRequestMessage to send.

cancellationToken CancellationToken

A token for canceling the request.

Returns

Task<HttpResponseMessage>

A task that represents the asynchronous operation, with a result of the HttpResponseMessage received in response to the request.

Remarks

This method sends the provided HTTP request and returns the response if the status code indicates a success. For any error status codes, it fails fast by throwing an exception specific to the nature of the error. Additionally, the method incorporates pre-send and post-receive hooks for adding custom logic, such as modifying request headers or logging response details.

Exceptions

HttpResponseException

Thrown if the response status code indicates a failure.

HttpRequestException

Thrown if the request fails due to an underlying issue such as network connectivity, DNS failure, server certificate validation, or timeout.

OperationCanceledException

Thrown if the operation is canceled via the cancellation token.

DispatchWithRetriesAsync(HttpRequestMessage, CancellationToken)

Sends an asynchronous HTTP request, with the possibility of retrying the request based on specific failure conditions.

protected virtual Task<HttpResponseMessage> DispatchWithRetriesAsync(HttpRequestMessage request, CancellationToken cancellationToken = default)

Parameters

request HttpRequestMessage

The HttpRequestMessage to send.

cancellationToken CancellationToken

A token for canceling the request (optional).

Returns

Task<HttpResponseMessage>

A task that represents the asynchronous operation, with a result of the HttpResponseMessage received in response to the request.

Remarks

This method is responsible for sending the HTTP request and optionally retrying it under specific failure conditions. The decision to retry a request is based on the nature of the failure, with potential consultation of external retry logic mechanisms.

Exceptions

ArgumentNullException

Thrown if request is null.

HttpResponseException

Thrown if the response status code indicates a failure.

HttpRequestException

Thrown if the request fails due to an underlying issue such as network connectivity, DNS failure, server certificate validation, or timeout.

OperationCanceledException

Thrown if the operation is canceled via the cancellation token.

See Also

Dispose()

Releases the unmanaged resources used by the HttpRestClient and optionally disposes of the managed resources.

public void Dispose()

Dispose(bool)

Disposes the HttpRestClient instance.

protected virtual void Dispose(bool disposing)

Parameters

disposing bool

Indicates whether the method is called from a Dispose() method.

~HttpRestClient()

Releases unmanaged resources.

protected ~HttpRestClient()

OnAfterReceivingResponse(HttpResponseMessage)

Raises the AfterReceivingResponse event.

protected virtual void OnAfterReceivingResponse(HttpResponseMessage response)

Parameters

response HttpResponseMessage

The HTTP response message that was received.

Remarks

This method is called to trigger the AfterReceivingResponse event. This allows to react to the reception of an HTTP response. The method is invoked after a response is received from an HTTP request but before any processing is performed on the response.

OnBeforeSendingRequest(HttpRequestMessage)

Raises the BeforeSendingRequest event.

protected virtual void OnBeforeSendingRequest(HttpRequestMessage request)

Parameters

request HttpRequestMessage

The HTTP request message that was created.

Remarks

This method is called to trigger the BeforeSendingRequest event. This allows for centralized handling of request modifications across various methods that send HTTP requests. The method is invoked before an HttpRequestMessage is sent.

OnDisposing()

Raises the Disposing event.

protected virtual void OnDisposing()

SendAsync(HttpMethod, string, HttpContent?, CancellationToken)

Sends an asynchronous HTTP request with the specified method, URI, and payload, without processing the response body.

public virtual Task<HttpResponseMessage> SendAsync(HttpMethod method, string uri, HttpContent? payload = null, CancellationToken cancellationToken = default)

Parameters

method HttpMethod

The HTTP method to use for the request.

uri string

The URI to which the request is sent.

payload HttpContent

The HTTP request payload content (optional).

cancellationToken CancellationToken

A token for canceling the request (optional).

Returns

Task<HttpResponseMessage>

A task that represents the asynchronous operation. The task result contains the response.

Exceptions

ArgumentNullException

Thrown if method or uri is null.

HttpResponseException

Thrown if the response status code indicates a failure.

HttpRequestException

Thrown if the request fails due to an underlying issue such as network connectivity, DNS failure, server certificate validation, or timeout.

OperationCanceledException

Thrown if the operation is canceled via the cancellation token.

SendAsync<T>(HttpMethod, string, HttpContent?, CancellationToken)

Sends an asynchronous HTTP request with the specified method, URI, and payload, returning response body deserialized as the specified type.

public virtual Task<T?> SendAsync<T>(HttpMethod method, string uri, HttpContent? payload = null, CancellationToken cancellationToken = default)

Parameters

method HttpMethod

The HTTP method to use for the request.

uri string

The URI to which the request is sent.

payload HttpContent

The HTTP request payload content (optional).

cancellationToken CancellationToken

A token for canceling the request (optional).

Returns

Task<T>

A task that represents the asynchronous operation, with a result of the specified type.

Type Parameters

T

The type of the response object.

Exceptions

ArgumentNullException

Thrown if method or uri is null.

HttpResponseException

Thrown if the response status code indicates a failure.

HttpRequestException

Thrown if the request fails due to an underlying issue such as network connectivity, DNS failure, server certificate validation, or timeout.

HttpContentException

Thrown if the response body is empty or its media type is not supported.

OperationCanceledException

Thrown if the operation is canceled via the cancellation token.

ToExceptionAsync(HttpResponseMessage, CancellationToken)

Converts an HttpResponseMessage into an appropriate exception.

protected virtual Task<HttpResponseException> ToExceptionAsync(HttpResponseMessage response, CancellationToken cancellationToken)

Parameters

response HttpResponseMessage

The HTTP response message to convert.

cancellationToken CancellationToken

A token for canceling the operation.

Returns

Task<HttpResponseException>

A task that represents the asynchronous operation. The task result contains an HttpResponseException object that represents the error extracted from the response.

Remarks

This method endeavors to deserialize the response content into a ResponseErrorType, provided that the type is specified and implements the IHttpErrorResponse interface. Upon successful deserialization, the resulting data is transformed into an exception. If deserialization fails, a generic HttpResponseException is generated, incorporating the response's status code and a default error message.

Exceptions

ArgumentNullException

Thrown if response is null.

See Also

Events

AfterReceivingResponse

Occurs when an HTTP response has been received.

public event EventHandler<HttpResponseMessageEventArgs>? AfterReceivingResponse

Event Type

EventHandler<HttpResponseMessageEventArgs>

Remarks

This event is raised after an HTTP response is received but before the response is processed further. It provides a way for subscribers to inspect the HttpResponseMessage. This can be useful for logging response details, handling specific HTTP status codes, or modifying the response content or headers before they are processed by the rest of the application.

BeforeSendingRequest

Occurs when a new HTTP request message is about to be sent.

public event EventHandler<HttpRequestMessageEventArgs>? BeforeSendingRequest

Event Type

EventHandler<HttpRequestMessageEventArgs>

Remarks

This event provides an opportunity for subscribers to modify the HttpRequestMessage before it is sent. Common modifications include adding custom headers, changing request properties, or logging request information. Modifications made to the request in this event are included in the outgoing HTTP request.

Disposing

Occurs just before the HttpRestClient is disposed.

public event EventHandler<EventArgs>? Disposing

Event Type

EventHandler<EventArgs>

Remarks

This event provides a way for subscribers to perform cleanup or other actions before the client is disposed.