Skip to main content

RA.Utilities.Integrations

· 8 min read
Redon Alla
.NET, React, Angular Developer

Version 10.2.1​

Date Badge NuGet version

ProxySettings is removed entirely. v10.2.0 had already removed the built-in proxy pipeline (ProxyMessageHandler, WithProxyFromSettings<TSettings>(...)) and kept ProxySettings as a configuration-only POCO; the class itself is now gone.

⚠️ Breaking Changes​

  • ProxySettings removed: the RA.Utilities.Integrations.Options.ProxySettings class is deleted. Applications that kept it as a bindable options POCO must define their own proxy options type and wire the primary handler explicitly. The UseProxy flag on IIntegrationSettings/BaseApiSettings<T> still exists but remains unconsumed by any package component. Migration:
// Before (v10.2.0)
public class MyApiSettings : BaseApiSettings<MyApiActions>
{
public ProxySettings? Proxy { get; set; }
}

// After (v10.2.1) — own options POCO
public sealed class ProxyOptions
{
[Required, Url] public string Address { get; set; } = default!;
public string? Username { get; set; }
public string? Password { get; set; }
public bool BypassProxyOnLocal { get; set; }
}

public class MyApiSettings : BaseApiSettings<MyApiActions>
{
public ProxyOptions? Proxy { get; set; }
}

// Wire the proxy yourself:
builder.Services.AddHttpClient("MyApi")
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler
{
Proxy = new WebProxy(proxyOptions.Address),
UseProxy = true
});

Version 10.2.0​

Date Badge NuGet version

This release consolidates the registration API into C# 14 extension members grouped one class per receiver type, renames the logging infrastructure (RequestResponseLoggingHandler becomes LoggingHandler), and removes the built-in API key and proxy machinery.

⚠️ Breaking Changes​

  • DependencyInjectionExtensions split into ServiceCollectionExtensions and HttpClientBuilderExtensions: the IServiceCollection methods (AddHttpClientIntegration, AddScopedHttpMessageHandler<T>, AddTransientHttpMessageHandler<T>) now live in ServiceCollectionExtensions, and the IHttpClientBuilder pipeline methods live in HttpClientBuilderExtensions. The namespace, method names, and signatures are unchanged — only code that references the class by name needs updating.
- var t = typeof(DependencyInjectionExtensions);
+ var t = typeof(ServiceCollectionExtensions); // or HttpClientBuilderExtensions
  • Pipeline methods renamed: WithHttpLoggingHandler() → AddLoggingHandler() and WithInternalHeadersForwardingHandler() → AddInternalHeadersForwardingHandler().

  • RequestResponseLoggingHandler renamed to LoggingHandler: its constructor still takes only an ILogger<LoggingHandler>; update manual constructions and AddScopedHttpMessageHandler<RequestResponseLoggingHandler>() registrations.

  • HttpRequestMessageExtensions renamed to HttpRequestOptionsExtensions: GetClientIpAddress() call sites are unchanged; the ToDictionary(...) helper was removed.

  • API key support removed: IApiKeySettings, ApiKeyAuthenticationHandler<TSettings>, WithApiKey(...), and WithApiKeyFromSettingsHandler<TSettings>() are gone. Use ConfigureHttpClient for a static key or a custom DelegatingHandler for dynamic ones.

  • Proxy support removed: IProxySettings, ProxyMessageHandler, and WithProxyFromSettings<TSettings>(...) are gone. ProxySettings remains as a configuration-only POCO; use ConfigurePrimaryHttpMessageHandler to route a client through a proxy. The UseProxy flag on IIntegrationSettings/BaseApiSettings<T> is no longer consumed by any built-in component.

🔄 Behavior Changes​

  • InternalHeadersForwardHandler reads headers per request: instead of capturing the Authorization and x-request-id headers once in the constructor (which could go stale when the pooled handler instance is reused), the handler now reads the current values from IHttpContextAccessor.HttpContext on every SendAsync. No code changes are required.

📝 Improvements​

  • C# 14 extension members: ServiceCollectionExtensions, HttpClientBuilderExtensions, and HttpRequestOptionsExtensions declare their methods inside extension(...) blocks. Extension-method call sites keep compiling unchanged — only class-name references (typeof(...), static calls, reflection strings) need updating.

See the Migration Guide for detailed before/after examples.


Version 10.1.1​

Date Badge NuGet version

RequestResponseLoggingHandler is simplified and its slow-call logging made explicit: the handler now takes only an ILogger, and calls that exceed the warning threshold produce a dedicated Warning entry in addition to the Information request/response logs.

⚠️ Breaking Changes​

  • RequestResponseLoggingHandler constructor simplified: the IHttpContextAccessor parameter was removed.
- public RequestResponseLoggingHandler(ILogger<RequestResponseLoggingHandler> logger, IHttpContextAccessor httpContextAccessor)
+ public RequestResponseLoggingHandler(ILogger<RequestResponseLoggingHandler> logger)

WithHttpLoggingHandler() handles the new signature automatically — only manual constructions/registrations need updating.

  • Log templates no longer carry RequestId / TraceIdentifier (via RA.Utilities.Logging.Shared 10.0.2): correlation now comes from the ambient log scope (LoggingConstants.XRequestId), e.g. the one created by LoggingMiddleware or the Serilog RequestIdEnricher.

✨ Enhancements​

  • Dedicated slow-call warning: when a call exceeds the handler's warning threshold (35 seconds), an additional Warning entry is written alongside the Information response log.
_logger.LogInformation("HttpClient Response: {@ResponseDto}", responseDto);

+ if (stopwatch.Elapsed.TotalMilliseconds > _warningThresholdMilliseconds)
+ _logger.LogWarning("HttpClient call to {Method} {Url} took too long ({ElapsedMilliseconds} ms)", ...);

Version 10.1.0​

Date Badge NuGet version

This release overhauls the BaseHttpClient API with support for all four HTTP verbs and strongly-typed query string and header parameters, backed by a new Roslyn incremental source generator.

✨ New Features​

  • Full HTTP Verb Coverage: BaseHttpClient now provides GetAsync, PostAsync, PutAsync and DeleteAsync — each with a typed-response overload and a string overload — covering the complete CRUD surface for external APIs.

  • Strongly-Typed Query String Parameters: Mark a partial class with [QueryParameters] and the source generator implements IQueryStringRequest for it, mapping each public property to a query string key-value pair. Null values are skipped, bool values are formatted as true/false, DateTime/DateTimeOffset values use the round-trip format, and collections are emitted as repeated keys. Override the emitted key per property with [QueryParameterName("...")].

  • Strongly-Typed Header Parameters: Mark a partial class with [HeaderParameters] and the generator implements the new IHeaderRequest contract, mapping each public property to an HTTP header. Override the header name per property with [HeaderParameterName("...")], e.g. x-request-id.

  • Compile-Time Code Generation: A new incremental Roslyn source generator, shipped inside the package as an analyzer, generates the parameter mappings at compile time — giving full IntelliSense and compile-time safety, with zero reflection.

  • Null-Safe Requests: Query and header parameters are optional; passing null builds a plain request instead of throwing.

  • JSON Request Bodies: PostAsync and PutAsync serialize request bodies as JSON (application/json; charset=utf-8) with camel-case property naming.

  • Query String Utilities: The query string building logic is consolidated into the new QueryUtilities class, which replaces the old DictionaryExtensions.ToQueryString(...) extension.

⚠️ Breaking Changes​

  • IIntegrationSettings no longer carries MediaType/Encoding; JSON is now the fixed content type.
  • BaseHttpClient methods now accept IHeaderRequest? instead of Dictionary<string, string>? for headers.
  • Typed-response overloads now return Task<TResponse?> and yield null for empty response bodies.
  • AddOptionWithValidations(...) was removed from DependencyInjectionExtensions; use AddHttpClientIntegration for validated integration settings.
  • DictionaryExtensions.ToQueryString(...) was removed; use QueryUtilities.ToQueryString(QueryParams?) instead.
  • See the Migration Guide for detailed before/after examples.

🚀 Getting Started​

using RA.Utilities.Integrations.Attributes;

[QueryParameters]
public partial class GetProductsQuery
{
[QueryParameterName("category_id")]
public int? CategoryId { get; init; }
}

[HeaderParameters]
public partial class RequestHeaders
{
[HeaderParameterName("x-request-id")]
public string? XCorrelationId { get; init; }
}

Product? product = await client.GetAsync<Product>(
"products",
new GetProductsQuery { CategoryId = 5 },
new RequestHeaders { XCorrelationId = "trace-1" });

await client.PostAsync<Product, Product>("products", product);
await client.PutAsync<Product, Product>($"products/{product.Id}", product);
await client.DeleteAsync("products/1");

Version 10.0.1​

Date Badge NuGet version

This release focuses on internal dependency updates and version synchronization within the RA.Utilities ecosystem.

✨ Improvements​

  • Ecosystem Alignment: Updated internal project references to RA.Utilities.Core.Constants and RA.Utilities.Logging.Shared to version 10.0.1.
  • Consistency: Synchronized the package version to maintain parity with the core components following the introduction of new semantic exceptions.

Version 10.0.0​

Date Badge NuGet version

Updated package version 10.0.9-rc (release candidate) to 10.0.0, indicating a transition to a stable release. This change signifies that the project is no longer in the release candidate phase and is considered ready for production use, reflecting confidence in its stability and completeness.

Version 10.0.0-rc.2​

Date Badge NuGet version

This release modernizes the RA.Utilities.Integrations package, providing a robust and repeatable pattern for managing external API integrations. It centralizes configuration, simplifies registration, and improves resilience with built-in retry policies.

✨ New Features​

  • Standardized Configuration: Centralizes HTTP client settings (Base URL, timeouts, headers) in appsettings.json using the HttpClientSettings base class.
  • Simplified Registration: Introduced the AddIntegrationHttpClient<TClient, TSettings> extension method to register a typed HttpClient, bind its configuration, and apply default policies with a single line of code.
  • Built-in Resilience: Includes a default transient error handling policy (retry with exponential backoff) using Polly, improving the reliability of external API calls.
  • Promotes Best Practices: Encourages the use of typed HttpClients via IHttpClientFactory, which provides better compile-time safety, intellisense, and connection management.
  • Updated Documentation: The README.md has been updated to provide a clear, step-by-step guide for setting up a typed client, from configuration to implementation.