diff --git a/ManagedCode.Communication.Extensions/Http/ResultHttpClientExtensions.cs b/ManagedCode.Communication.Extensions/Http/ResultHttpClientExtensions.cs
new file mode 100644
index 0000000..b5a2a57
--- /dev/null
+++ b/ManagedCode.Communication.Extensions/Http/ResultHttpClientExtensions.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using ManagedCode.Communication;
+using ManagedCode.Communication.Extensions;
+using Polly;
+
+namespace ManagedCode.Communication.Extensions.Http;
+
+///
+/// Helpers that execute requests and transform the responses into
+/// instances.
+///
+public static class ResultHttpClientExtensions
+{
+ ///
+ /// Sends a request built by and converts the HTTP response into a
+ /// . When a is provided the request is executed through it,
+ /// enabling Polly resilience strategies such as retries or circuit breakers.
+ ///
+ /// The JSON payload type that the endpoint returns in case of success.
+ /// The used to send the request.
+ /// Factory that creates a fresh for each attempt.
+ /// Optional Polly resilience pipeline that wraps the HTTP invocation.
+ /// Token that cancels the request execution.
+ public static Task> SendForResultAsync(
+ this HttpClient client,
+ Func requestFactory,
+ ResiliencePipeline? pipeline = null,
+ CancellationToken cancellationToken = default)
+ {
+ ArgumentNullException.ThrowIfNull(client);
+ ArgumentNullException.ThrowIfNull(requestFactory);
+
+ return SendCoreAsync(
+ client,
+ requestFactory,
+ static response => response.FromJsonToResult(),
+ pipeline,
+ cancellationToken);
+ }
+
+ ///
+ /// Sends a request built by and converts the HTTP response into a
+ /// without a payload. When a is provided the request is executed
+ /// through it, enabling Polly resilience strategies such as retries or circuit breakers.
+ ///
+ /// The used to send the request.
+ /// Factory that creates a fresh for each attempt.
+ /// Optional Polly resilience pipeline that wraps the HTTP invocation.
+ /// Token that cancels the request execution.
+ public static Task SendForResultAsync(
+ this HttpClient client,
+ Func requestFactory,
+ ResiliencePipeline? pipeline = null,
+ CancellationToken cancellationToken = default)
+ {
+ ArgumentNullException.ThrowIfNull(client);
+ ArgumentNullException.ThrowIfNull(requestFactory);
+
+ return SendCoreAsync(
+ client,
+ requestFactory,
+ static response => response.FromRequestToResult(),
+ pipeline,
+ cancellationToken);
+ }
+
+ ///
+ /// Performs a GET request for and converts the response into a
+ /// . The optional allows attaching Polly retry or circuit
+ /// breaker strategies.
+ ///
+ /// The JSON payload type that the endpoint returns in case of success.
+ /// The used to send the request.
+ /// The request URI.
+ /// Optional Polly resilience pipeline that wraps the HTTP invocation.
+ /// Token that cancels the request execution.
+ public static Task> GetAsResultAsync(
+ this HttpClient client,
+ string requestUri,
+ ResiliencePipeline? pipeline = null,
+ CancellationToken cancellationToken = default)
+ {
+ ArgumentNullException.ThrowIfNull(client);
+ ArgumentException.ThrowIfNullOrEmpty(requestUri);
+
+ return client.SendForResultAsync(
+ () => new HttpRequestMessage(HttpMethod.Get, requestUri),
+ pipeline,
+ cancellationToken);
+ }
+
+ ///
+ /// Performs a GET request for and converts the response into a non generic
+ /// .
+ ///
+ /// The used to send the request.
+ /// The request URI.
+ /// Optional Polly resilience pipeline that wraps the HTTP invocation.
+ /// Token that cancels the request execution.
+ public static Task GetAsResultAsync(
+ this HttpClient client,
+ string requestUri,
+ ResiliencePipeline? pipeline = null,
+ CancellationToken cancellationToken = default)
+ {
+ ArgumentNullException.ThrowIfNull(client);
+ ArgumentException.ThrowIfNullOrEmpty(requestUri);
+
+ return client.SendForResultAsync(
+ () => new HttpRequestMessage(HttpMethod.Get, requestUri),
+ pipeline,
+ cancellationToken);
+ }
+
+ private static async Task SendCoreAsync(
+ HttpClient client,
+ Func requestFactory,
+ Func> convert,
+ ResiliencePipeline? pipeline,
+ CancellationToken cancellationToken)
+ {
+ if (pipeline is null)
+ {
+ using var request = requestFactory();
+ using var directResponse = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
+ return await convert(directResponse).ConfigureAwait(false);
+ }
+
+ var httpResponse = await pipeline.ExecuteAsync(
+ async cancellationToken =>
+ {
+ using var request = requestFactory();
+ return await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
+ },
+ cancellationToken).ConfigureAwait(false);
+
+ using (httpResponse)
+ {
+ return await convert(httpResponse).ConfigureAwait(false);
+ }
+ }
+}
diff --git a/ManagedCode.Communication.Extensions/ManagedCode.Communication.Extensions.csproj b/ManagedCode.Communication.Extensions/ManagedCode.Communication.Extensions.csproj
new file mode 100644
index 0000000..1693656
--- /dev/null
+++ b/ManagedCode.Communication.Extensions/ManagedCode.Communication.Extensions.csproj
@@ -0,0 +1,22 @@
+
+
+
+ true
+ embedded
+
+
+
+
+ ManagedCode.Communication.Extensions
+ ManagedCode.Communication.Extensions
+ Optional integrations for ManagedCode.Communication including Minimal API endpoint filters.
+ managedcode;communication;result-pattern;minimal-api;endpoint-filter
+
+
+
+
+
+
+
+
+
diff --git a/ManagedCode.Communication.Extensions/MinimalApi/CommunicationEndpointExtensions.cs b/ManagedCode.Communication.Extensions/MinimalApi/CommunicationEndpointExtensions.cs
new file mode 100644
index 0000000..8e7a6a7
--- /dev/null
+++ b/ManagedCode.Communication.Extensions/MinimalApi/CommunicationEndpointExtensions.cs
@@ -0,0 +1,46 @@
+using System;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Routing;
+
+namespace ManagedCode.Communication.Extensions.MinimalApi;
+
+///
+/// Extension helpers for wiring ManagedCode.Communication support into Minimal API route handlers.
+///
+public static class CommunicationEndpointExtensions
+{
+ ///
+ /// Adds to a specific so that
+ /// Result-returning handlers are converted into automatically.
+ ///
+ /// The endpoint builder.
+ /// The same builder instance to enable fluent configuration.
+ public static RouteHandlerBuilder WithCommunicationResults(this RouteHandlerBuilder builder)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddEndpointFilterFactory(CreateFilter);
+ return builder;
+ }
+
+ ///
+ /// Adds to an entire so that every child endpoint
+ /// inherits automatic Result to conversion.
+ ///
+ /// The group builder.
+ /// The same builder instance for chaining.
+ public static RouteGroupBuilder WithCommunicationResults(this RouteGroupBuilder builder)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddEndpointFilterFactory(CreateFilter);
+ return builder;
+ }
+
+ private static EndpointFilterDelegate CreateFilter(EndpointFilterFactoryContext context, EndpointFilterDelegate next)
+ {
+ var filter = new ResultEndpointFilter();
+ return invocationContext => filter.InvokeAsync(invocationContext, next);
+ }
+}
diff --git a/ManagedCode.Communication.Extensions/MinimalApi/ResultEndpointFilter.cs b/ManagedCode.Communication.Extensions/MinimalApi/ResultEndpointFilter.cs
new file mode 100644
index 0000000..7b86cc7
--- /dev/null
+++ b/ManagedCode.Communication.Extensions/MinimalApi/ResultEndpointFilter.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Collections.Concurrent;
+using System.Threading.Tasks;
+using ManagedCode.Communication;
+using ManagedCode.Communication.AspNetCore.Extensions;
+using ManagedCode.Communication.Constants;
+using Microsoft.AspNetCore.Http;
+using HttpResults = Microsoft.AspNetCore.Http.Results;
+using AspNetResult = Microsoft.AspNetCore.Http.IResult;
+using CommunicationResult = ManagedCode.Communication.IResult;
+using CommunicationResultOfObject = ManagedCode.Communication.IResult