Nextended.ResponseFilters
10.1.5
See the version list below for details.
dotnet add package Nextended.ResponseFilters --version 10.1.5
NuGet\Install-Package Nextended.ResponseFilters -Version 10.1.5
<PackageReference Include="Nextended.ResponseFilters" Version="10.1.5" />
<PackageVersion Include="Nextended.ResponseFilters" Version="10.1.5" />
<PackageReference Include="Nextended.ResponseFilters" />
paket add Nextended.ResponseFilters --version 10.1.5
#r "nuget: Nextended.ResponseFilters, 10.1.5"
#:package Nextended.ResponseFilters@10.1.5
#addin nuget:?package=Nextended.ResponseFilters&version=10.1.5
#tool nuget:?package=Nextended.ResponseFilters&version=10.1.5
Nextended.ResponseFilters
Fluent, attribute-aware response-filtering pipeline for redacting, masking, or transforming object graphs before serialization.
A ResponseFilter<T> looks like a FluentValidator<T> — but instead of validating, it mutates the DTO right before it leaves your service: null out fields the user must not see, mask emails, replace internal flags, drop collection items conditionally.
Installation
dotnet add package Nextended.ResponseFilters
# ASP.NET Core integration:
dotnet add package Nextended.ResponseFilters.AspNetCore
Quick Start
public class OrderResponseFilter : ResponseFilter<OrderDto>
{
public OrderResponseFilter()
{
// Null out cost fields unless the user has the "Finance" role
Nullify(x => x.TotalCost, x => x.UnitCost)
.Unless(WhenInstance(_ => HasRole("Finance")));
// Mask the email for unauthenticated callers
Replace(x => x.CustomerEmail)
.With("***@***.***")
.When((order, ctx) => !ctx.Services.GetRequiredService<ICurrentUser>().IsAuthenticated);
// Truncate notes after 200 chars
Transform(x => x.Notes)
.Using(n => n?.Length > 200 ? n[..200] + "…" : n)
.Always();
// Recurse into a collection — each line item gets its own sub-filter
ForEach(x => x.Lines, line =>
line.Nullify(l => l.UnitCost).Unless(_ => HasRole("Finance")));
}
private static bool HasRole(string role) => /* check current principal */ false;
}
Then wire it up:
// Program.cs / Startup.cs
services.AddResponseFilters(new[] { typeof(OrderResponseFilter).Assembly });
// Manually run it (e.g. in a worker service)
var pipeline = sp.GetRequiredService<IResponseFilterPipeline>();
await pipeline.ProcessAsync(myOrderDto, new ResponseFilterContext(sp));
For ASP.NET Core: see Nextended.ResponseFilters.AspNetCore — one extension call and every controller response is filtered automatically.
Concepts
| Concept | Purpose |
|---|---|
ResponseFilter<T> |
Abstract base class. Inherit, configure rules in the constructor. |
Nullify(...) |
Set one or more properties to null when predicate matches. |
Replace(...)With(...) |
Replace property with a constant or per-instance value. |
Transform(...)Using(...) |
Map a property through a function. |
ForEach(...) |
Recurse into a collection property; configure a sub-filter inline. |
.When(...) / .Unless(...) / .Always() / .WhenAll(...) / .WhenAny(...) |
Predicate vocabulary applied as the terminal step. |
IResponseFilterContext |
Per-request bag: IServiceProvider, CancellationToken, Items for memoizing async work. |
IResponseFilterPipeline |
Walks the object graph depth-first and applies all matching filters. |
IResponseFilterRegistry |
Resolves filters per type from DI. |
Why use this over attributes?
| Use case | Attribute | Fluent (ResponseFilter<T>) |
|---|---|---|
| Permission-based nulling | ✅ | ✅ |
| DTO from a 3rd-party library (no attribute access) | ❌ | ✅ |
| Masking instead of nulling | ❌ | ✅ |
| Conditional on another property | ❌ | ✅ |
| Tenant/user-context-aware | ❌ | ✅ |
| Unit-testable in isolation | ⚠️ | ✅ |
If your needs are simple (always-null-on-missing-permission), attributes are fine. Use this package when you need real conditional logic, transformation, or testability.
Performance
PropertyAccessoruses compiled Expression-Tree get/set delegates (cached perPropertyInfo) — typically 10-50× faster thanPropertyInfo.SetValue.TypeGraphInspectorcaches per-type metadata so the graph walker never reflects twice on the same type.- Cycle detection via
ReferenceEqualityComparerprevents infinite recursion on back-references. - No filter registered for a type ⇒ pipeline only walks children and returns immediately.
Robustness
Every filter and every property mutation is wrapped in a try/catch. If a single rule throws, it's logged via ILogger<ResponseFilterPipeline> and the rest of the pipeline continues — a misbehaving filter never takes down a request.
Supported Frameworks
- .NET 8.0, .NET 9.0, .NET 10.0
License
GPL-3.0-or-later (same as the rest of the Nextended ecosystem).
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. 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 is compatible. 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 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
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
- Nextended.Core (>= 10.1.5)
-
net8.0
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.2)
- Nextended.Core (>= 10.1.5)
-
net9.0
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.10)
- Nextended.Core (>= 10.1.5)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Nextended.ResponseFilters:
| Package | Downloads |
|---|---|
|
Nextended.ResponseFilters.AspNetCore
ASP.NET Core adapter for Nextended.ResponseFilters. Wires the filter pipeline into the MVC pipeline as a global IAsyncResultFilter, mutating ObjectResult.Value before serialization. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.1.20 | 68 | 7/26/2026 |
| 10.1.19 | 67 | 7/23/2026 |
| 10.1.18 | 106 | 7/22/2026 |
| 10.1.17 | 108 | 7/21/2026 |
| 10.1.16 | 112 | 7/21/2026 |
| 10.1.15 | 118 | 7/21/2026 |
| 10.1.14 | 113 | 7/16/2026 |
| 10.1.13 | 118 | 7/12/2026 |
| 10.1.12 | 121 | 7/12/2026 |
| 10.1.11 | 125 | 7/6/2026 |
| 10.1.10 | 142 | 6/16/2026 |
| 10.1.9 | 130 | 5/29/2026 |
| 10.1.8 | 135 | 5/19/2026 |
| 10.1.7 | 167 | 5/16/2026 |
| 10.1.6 | 1,117 | 5/12/2026 |
| 10.1.5 | 138 | 5/12/2026 |
| 10.1.5-pev-1 | 129 | 5/12/2026 |