Fluens.Web
0.8.2
dotnet add package Fluens.Web --version 0.8.2
NuGet\Install-Package Fluens.Web -Version 0.8.2
<PackageReference Include="Fluens.Web" Version="0.8.2" />
<PackageVersion Include="Fluens.Web" Version="0.8.2" />
<PackageReference Include="Fluens.Web" />
paket add Fluens.Web --version 0.8.2
#r "nuget: Fluens.Web, 0.8.2"
#:package Fluens.Web@0.8.2
#addin nuget:?package=Fluens.Web&version=0.8.2
#tool nuget:?package=Fluens.Web&version=0.8.2
Fluens.Web
ASP.NET Core base types for Fluens web libraries: Result-to-HTTP mapping, global exception handler, and paged responses.
Installation
dotnet add package Fluens.Web
Usage
fluensBuilder.AddWeb();
// In middleware pipeline
app.UseExceptionHandler(); // GlobalExceptionHandler returns ProblemDetails
ResultExtensions map Result / Result<T> to HTTP responses:
app.MapPost("/orders", async (CreateOrder cmd, ICommandDispatcher dispatcher, CancellationToken ct) =>
{
var result = await dispatcher.SendAsync(cmd, ct);
return result.ToHttpResult(); // 204 on success, 4xx/5xx on failure
});
Error mapping: NotFoundError → 404, ValidationError → 400, ConflictError → 409, ForbiddenError → 403, unknown Error → 500.
Client-aborted requests
When the client closes the connection (HttpContext.RequestAborted is cancelled), the exception that follows is a consequence of the abort, not a server error - e.g. SqlClient throws SqlException ("operation cancelled by user"), not OperationCanceledException. GlobalExceptionHandler then sets status 499, logs at Debug instead of Error and writes no body. Detection is by token, never by exception type or (localized) message, so pass the endpoint's CancellationToken through to handlers and EF Core. An OperationCanceledException raised while the request is still live (e.g. an HttpClient timeout) stays a 500 with an Error log. ASP.NET Core itself already answers 499 for an OperationCanceledException/IOException thrown after the abort, without calling the handler.
Server-Side Localization
Pass an optional IStringLocalizer to translate error messages server-side. The Error.Message is used as the localization key and {Key} placeholders are replaced with MessageArgs values:
app.MapPost("/orders", async (
CreateOrder cmd,
ICommandDispatcher dispatcher,
IStringLocalizer<OrderErrors> localizer,
CancellationToken ct) =>
{
var result = await dispatcher.SendAsync(cmd, ct);
return result.ToHttpResult(localizer); // Translates error messages using localizer
});
When no localizer is provided (default), Error.Message is returned as-is — maintaining full backward compatibility. MessageArgs is always included in ProblemDetails.Extensions["messageArgs"] regardless of whether a localizer is used.
IServiceCatalog
IServiceCatalog is the central, synchronous service-resolution contract consumed by web libraries (HTTP, messaging) without depending on the underlying discovery implementation. It lives in the base project — like IHealthEndpointInfo — so consumers stay decoupled from the Consul-backed implementation in Fluens.Web.Discovery.
public interface IServiceCatalog
{
// One healthy endpoint for the service, or null when none is available.
ResolvedServiceEndpoint? Resolve(string serviceName);
// Services advertising the tag, optionally filtered by metadata key/value pairs.
IReadOnlyList<DiscoveredService> List(string tag, IReadOnlyDictionary<string, string>? metaMatch = null);
// Fires when the catalog snapshot changes (topology updates).
IChangeToken GetChangeToken();
}
The return types are immutable records:
var endpoint = catalog.Resolve("orders-api");
Uri uri = endpoint?.ToUri(); // scheme://host:port/
foreach (var service in catalog.List("fluens-mesh", new Dictionary<string, string> { ["fluens-cluster"] = "c1" }))
{
ResolvedServiceEndpoint? first = service.FirstHealthyEndpoint; // null when no endpoints
}
ResolvedServiceEndpoint(string Scheme, string Host, int Port)—ToUri()composes an absolutescheme://host:port/URI.DiscoveredService(string ServiceName, IReadOnlyList<ResolvedServiceEndpoint> Endpoints, IReadOnlyList<string> Tags, IReadOnlyDictionary<string, string> Meta)—FirstHealthyEndpointreturns the first endpoint ornullwhenEndpointsis empty.
TranslatableMessageExtensions
Translate TranslatableMessage instances (from Fluens.Kernel.Translations) using ASP.NET Core IStringLocalizer:
var message = new TranslatableMessage("order.status.changed")
.WithArg("orderId", "ORD-123")
.WithArg("newStatus", "Shipped");
// Translate using IStringLocalizer — Code is the localization key,
// {Key} placeholders are replaced with Args values
string translated = message.Translate(localizer);
PagedResponse<T>
PagedResponse<T> (namespace Fluens.Web.Paging) is the abstract, JSON-serializable base class for a paginated API response. It wraps a PagedResult<T> (from Fluens.Paging) and copies its pagination metadata onto [JsonInclude] properties, so a derived response serializes them without a public setter:
public abstract class PagedResponse<T>
{
protected PagedResponse(PagedResult<T> items, IReadOnlyCollection<string>? orderSelectorKeys = null);
[JsonInclude] public long TotalPages { get; }
[JsonInclude] public long TotalItems { get; }
[JsonInclude] public IReadOnlyList<T> Items { get; }
[JsonInclude] public int Page { get; }
[JsonInclude] public int PageSize { get; }
[JsonInclude] public IReadOnlyCollection<string>? OrderSelectorKeys { get; }
}
Page and PageSize are copied verbatim from the PagedResult<T> passed to the constructor - PageSize is the requested page size, not Items.Count. Both serialize as page and pageSize in the web camelCase JSON convention.
Define a derived response for your endpoint's item type:
public sealed class OrdersResponse : PagedResponse<OrderDto>
{
public OrdersResponse(PagedResult<OrderDto> result, IReadOnlyCollection<string>? orderSelectorKeys = null)
: base(result, orderSelectorKeys)
{
}
}
app.MapGet("/orders", async (IQueryDispatcher dispatcher, CancellationToken ct) =>
{
PagedResult<OrderDto> result = await dispatcher.SendAsync(new ListOrdersQuery(), ct);
return Results.Ok(new OrdersResponse(result));
});
License
This project is licensed under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- Fluens (>= 0.8.2)
- Fluens.Extensions (>= 0.8.2)
- Fluens.Kernel (>= 0.8.2)
NuGet packages (10)
Showing the top 5 NuGet packages that depend on Fluens.Web:
| Package | Downloads |
|---|---|
|
Fluens.Web.Contexts
CorrelationId propagation, context accessors, and consumed message context for ASP.NET Core applications. |
|
|
Fluens.Web.Api
Endpoint discovery, OpenAPI documentation with Scalar UI, and fixed-window rate limiting for ASP.NET Core minimal APIs. |
|
|
Fluens.Web.Validation
FluentValidation integration for ASP.NET Core minimal API endpoints with automatic request validation. |
|
|
Fluens.Web.Cors
CORS configuration and middleware setup for Fluens web applications. |
|
|
Fluens.Web.Auth
JWT Bearer authentication and security headers middleware for Fluens web applications. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.8.2 | 6 | 10/5/2026 |
| 0.8.1 | 221 | 9/15/2026 |
| 0.8.0 | 182 | 9/15/2026 |
| 0.7.11 | 185 | 9/15/2026 |
| 0.7.10 | 189 | 9/13/2026 |
| 0.7.9 | 206 | 9/11/2026 |
| 0.7.8 | 211 | 9/10/2026 |
| 0.7.7 | 212 | 9/10/2026 |
| 0.7.6 | 278 | 7/1/2026 |
| 0.7.5 | 244 | 6/22/2026 |
| 0.7.4 | 265 | 6/18/2026 |
| 0.7.2 | 230 | 6/18/2026 |
| 0.7.1 | 257 | 6/18/2026 |
| 0.6.6 | 333 | 3/11/2026 |
| 0.6.5 | 170 | 3/4/2026 |
| 0.6.4 | 165 | 3/4/2026 |
| 0.6.3 | 181 | 3/3/2026 |
| 0.6.2 | 179 | 3/2/2026 |
| 0.6.1 | 179 | 3/2/2026 |
| 0.6.0 | 172 | 3/1/2026 |