Nextended.ResponseFilters.AspNetCore
📚 Vollständige API-Referenz — jeder öffentliche Typ und Member, erzeugt aus der kompilierten Assembly.
Der ASP.NET-Core-Adapter für Nextended.ResponseFilters. Er hängt die Filter-Pipeline als globalen IAsyncResultFilter in MVC ein: Jeder ObjectResult.Value durchläuft vor der Serialisierung die konfigurierten Filter.
Installation
dotnet add package Nextended.ResponseFilters.AspNetCoreDer providerunabhängige Kern kommt transitiv mit — ein eigener Verweis auf Nextended.ResponseFilters ist nicht nötig.
Schnellstart
using Nextended.ResponseFilters;
using Nextended.ResponseFilters.AspNetCore;
builder.Services.AddNextendedResponseFilters(
assemblies: [typeof(OrderResponseFilter).Assembly]);Das ist alles. Der Aufruf
- registriert Pipeline, Registry und Optionen,
- durchsucht die angegebenen Assemblies nach
ResponseFilter<T>-Implementierungen, - registriert
ResponseFilterResultFilterund trägt ihn inMvcOptions.Filtersein.
Ohne Assembly-Angabe wird die aufrufende Assembly verwendet.
Konfiguration
builder.Services.AddNextendedResponseFilters(
assemblies: [typeof(OrderResponseFilter).Assembly],
lifetime: ServiceLifetime.Scoped,
configure: opts =>
{
opts.ExceptionBehavior = FilterExceptionBehavior.LogAndContinue;
opts.SkipResponseType = t => t.Namespace?.StartsWith("Volo.Abp") == true;
// Schranke pro Request — nur /api/app/* durchläuft die Pipeline
opts.ShouldHandle = (request, type) =>
Task.FromResult(request.Path.StartsWithSegments("/api/app"));
});Die vollständige Optionsreferenz steht auf der Seite zum Kernpaket.
Was der Adapter tut
Controller gibt ObjectResult(value) zurück
│
▼
ResponseFilterResultFilter.OnResultExecutionAsync
│
├─ kein ObjectResult oder Value ist null? ── durchlassen
├─ ShouldHandle(request, valueType) false? ── durchlassen
▼
IResponseFilterPipeline.ProcessAsync(value, context)
│ Wertregeln verändern das DTO direkt
│ Strukturregeln landen im StructuralEditBook
▼
StructuralEdits.HasAny?
│ ja ─▶ JsonStructuralTransformer.Transform(value, edits, jsonOptions)
│ ObjectResult.Value = JsonNode
│ ObjectResult.DeclaredType = null
▼
weiter an den MVC-FormatterZwei Details, die leicht übersehen werden:
Die JSON-Optionen kommen aus Ihrer Anwendung. Der Transformer holt sich IOptions<JsonOptions> aus dem Request-Scope. Ihre JsonNamingPolicy und Ihre [JsonPropertyName]-Attribute gelten also auch für umbenannte und hinzugefügte Schlüssel.
DeclaredType wird zurückgesetzt. Sobald der Wert ein JsonNode ist, muss die deklarierte Typinformation weg — sonst versucht der Formatter, den Baum in die Form des ursprünglichen DTO-Typs zu pressen. Der Adapter erledigt das.
Nur wenn es etwas zu tun gibt
Die Pipeline hat mehrere Kurzschlüsse, bevor überhaupt ein Objektgraph durchlaufen wird:
- Kein
ObjectResultoderValueistnull→ nichts passiert. ShouldHandleliefertfalse→ nichts passiert.SkipResponseTypetrifft zu → nichts passiert.- Die Erreichbarkeitsanalyse findet im Typgraphen keinen registrierten Zieltyp → nichts passiert.
Erst danach beginnt die Tiefensuche. Eine Anwendung, in der nur zwei DTOs Filter haben, zahlt für alle übrigen Endpunkte praktisch nichts.
Ohne MVC
Wenn Sie Minimal APIs, gRPC oder einen eigenen Transport verwenden, nehmen Sie nur den Kern und steuern die Pipeline selbst:
using Nextended.ResponseFilters.Extensions;
services.AddResponseFilters([typeof(OrderResponseFilter).Assembly]);await pipeline.ProcessAsync(dto, context);
if (context.StructuralEdits.HasAny)
{
var node = JsonStructuralTransformer.Transform(dto, context.StructuralEdits, jsonOptions);
return Results.Json(node);
}
return Results.Ok(dto);Den IResponseFilterContext implementieren Sie dabei selbst — er braucht nur Services, CancellationToken, Items und StructuralEdits.
Unterstützte Frameworks
net8.0net9.0net10.0