Programmierung und Softwareentwicklung

So verwenden Sie Unions und geschlossene Typhierarchien in ASP.NET Core

Der .NET-Blog erklärt, wie Unions und geschlossene Typhierarchien mit System.Text.Json über Minimal APIs, MVC, SignalR, Blazor und OpenAPI eingesetzt werden. Außerdem werden Mehrdeutigkeitsfälle und Bindungsquellen genannt, die diese Typen nicht unterstützen.

2026-09-10
5 Min. Lesezeit
11 Aufrufe
فريق تحرير certi.news
So verwenden Sie Unions und geschlossene Typhierarchien in ASP.NET Core

ASP.NET Core in .NET 11 bietet praktische Unterstützung für die Verwendung von Union-Typen und geschlossenen Typhierarchien mit System.Text.Json. Dadurch kann ein Wert dargestellt werden, der zu mehr als einem Typ oder zu einer bestimmten Typfamilie gehören kann. Die Unterstützung erstreckt sich auf Minimal APIs, MVC-Controller, SignalR, Blazor und OpenAPI-Dokumente, wobei es wichtige Unterschiede bei der Deserialisierung, Serialisierung und den Grenzen der Parameterbindung gibt.

Wann ist eine Union geeignet?

Eine Union eignet sich für Verträge, die unabhängige Alternativen akzeptieren, ohne dass ein JSON-Wrapper oder ein discriminator-Feld erforderlich ist. Beispiele sind ein Wert, der entweder eine Ganzzahl oder eine Zeichenfolge sein kann, oder eine Einstellung, die entweder einen booleschen Wert oder ein Objekt mit detaillierteren Optionen akzeptiert. Bei der Serialisierung wird der aktive Fall direkt in seiner natürlichen Form geschrieben; es wird weder ein spezieller Union-Wrapper noch ein discriminator hinzugefügt.

Fälle, die anhand der JSON-Struktur eindeutig unterschieden werden können, werden automatisch serialisiert. Wenn die Fälle jedoch dieselbe Struktur aufweisen, etwa bei einer Union mit den Objekten Cat und Dog, kann System.Text.Json den Typ nicht allein anhand des JSON-Tokens bestimmen. In diesem Fall kann ein benutzerdefinierter JsonTypeClassifier bereitgestellt werden, um den richtigen Fall auszuwählen. Dasselbe gilt für einige Anforderungsverträge, die eine Zahl oder eine Zeichenfolge akzeptieren. Die Web-JSON-Einstellungen erlauben das Lesen von Zahlen aus Zeichenfolgen, wodurch der Text als einer der beiden Fälle interpretiert werden kann.

Geschlossene Typhierarchien unterscheiden sich von Unions

Die Verwendung des Modifizierers closed bedeutet nicht, dass die polymorphe Serialisierung automatisch aktiviert wird. Bei der Verarbeitung eines konkreten abgeleiteten Typs wie PaymentAuthorized behandelt System.Text.Json ihn wie jeden anderen Typ und erzeugt JSON mit paymentId und amount, jedoch ohne discriminator.

Bei der Verwendung des Basistyps PaymentEvent in einer API muss dagegen der abzuleitende Typ festgelegt werden, der erstellt werden soll. Dies kann für den Basistyp mit JsonPolymorphic(InferClosedTypePolymorphism = true) oder über JsonSerializerOptions.InferClosedTypePolymorphism aktiviert werden. Anschließend leitet System.Text.Json die abgeleiteten Typen in der geschlossenen Hierarchie bei der Serialisierung ab und verwendet ihre Namen als Bezeichner, beispielsweise $type mit dem Wert PaymentAuthorized.

Die Wahl zwischen den beiden Modellen hängt von der Art des Vertrags ab: Eine Union stellt Alternativen dar, die nicht zu einer einzigen Familie gehören müssen, während geschlossene Hierarchien für eine zusammengehörige Gruppe von Ereignissen oder Entitäten geeignet sind, die einen eindeutigen discriminator benötigen.

Unterstützung in den ASP.NET-Core-Schichten

In Minimal APIs kann eine Union als Parameter des Anforderungstexts oder als Rückgabetyp verwendet werden, sowohl im üblichen Ausführungspfad als auch über den Request Delegate Generator, wobei sich beide Pfade gleich verhalten. Eine Union kann außerdem innerhalb eines anderen Modells, als Element eines IAsyncEnumerable<T> oder innerhalb eines Containers mit AsParameters auftreten. Die Einstellungen von ConfigureHttpJsonOptions wirken sich weiterhin auf die Serialisierung aus.

MVC-Controller unterstützen Unions als Aktionsparameter und Rückgabetypen, einschließlich Task<TUnion> und ValueTask<TUnion>. Da MVC die Einstellungen von JsonSerializerDefaults.Web verwendet, gilt auch hier das Problem der Mehrdeutigkeit zwischen Zahl und Zeichenfolge in HTTP-Eingaben.

In SignalR funktioniert die Unterstützung über JsonHubProtocol für Parameter, Rückgabewerte und Stream-Elemente. Eine Union vom Typ int oder string benötigt bei Verwendung dieses Protokolls keinen Classifier, da JsonHubProtocol das JSON-Token für eine Zeichenfolge in diesem Fall nicht als mehrdeutig behandelt. Unions, deren Fälle dasselbe Token StartObject verwenden, wie UnionPet(Cat, Dog), benötigen jedoch weiterhin einen Classifier. SignalR unterstützt diese Funktion nicht bei der Verwendung von MessagePack- oder Newtonsoft.Json-Hub-Protokollen.

Blazor und OpenAPI

Blazor-Komponentenparameter innerhalb des Prozesses werden direkt zugewiesen und benötigen daher keine Serialisierung. JavaScript-Interop, der gespeicherte Komponentenstatus und Parameter während des Prerenderings werden jedoch über System.Text.Json verarbeitet und folgen daher denselben Union-Regeln. So kann beispielsweise eine Union je nach aktivem Fall als Boolean oder als Optionsobjekt an JavaScript übergeben werden, ohne dass ein Wrapper oder discriminator hinzugefügt wird.

In OpenAPI wird eine Union mithilfe eines anyOf-Schemas dargestellt, das für jeden Fall einen Typ enthält. Die Fälle verwenden weiterhin dieselben Namen der Komponenten Cat und Dog, wenn sie als eigenständige Typen auftreten. Dies unterscheidet sich von polymorphen Typen mit discriminator, deren Schemas unter eindeutigen Namen veröffentlicht werden. ApiExplorer kann außerdem mehrere Antworttypen für denselben Statuscode und denselben Inhaltstyp innerhalb von anyOf darstellen.

Zu beachtende Einschränkungen

Die Unterstützung für Unions basiert auf System.Text.Json und funktioniert daher nicht mit Bindungsquellen, die keine JSON-Analyse durchlaufen. Dazu gehören Query-String-Werte, Pfadwerte, Header und Formularfelder. Ein Wert wie ?id=42 reicht nicht aus, um zu bestimmen, ob int, string oder Guid gemeint ist. In Blazor gilt diese Einschränkung auch für [SupplyParameterFromQuery] und die Formularbindung mit [SupplyParameterFromForm]. Der Quelle zufolge wird die Bindung von Unions aus diesen Quellen weiterhin geprüft und es werden Rückmeldungen dazu gesammelt.

Redaktionelle Einordnung: Der wesentliche Punkt ist hier nicht die Einführung eines neuen JSON-Formats, sondern die Vereinheitlichung des Umgangs mit Verträgen mit mehreren Fällen in weiten Teilen des .NET-11-Ökosystems. Der Erfolg des Designs hängt jedoch davon ab, ob die Fälle unterschieden werden können und aus welcher Datenquelle sie stammen. Daher sollte frühzeitig ein Classifier oder discriminator festgelegt werden, und es sollte nicht angenommen werden, dass die Unterstützung der Serialisierung automatisch die Unterstützung aller Arten der Parameterbindung bedeutet.

Nachrichtenquelle
ف
Autor

فريق تحرير certi.news

Aus derselben Kategorie

Das könnte Sie interessieren

Alle Nachrichten anzeigen