© DrHitch/Shutterstock.com
Web-APIs mit ASP.NET MVC 6

2 Formatter und Co.


Über Formatter können Entwickler die (De-)Serialisierung von Objekten und somit das Verhalten von Web-APIs steuern. Informationen über aufgerufene Operationen werden über ein zentrales Logging-Konzept geliefert.

Formatter

Zum Serialisieren und Deserialisieren von Objekten nutzt ASP.NET MVC 6, ähnlich wie auch die Vorgängerversion ASP.NET Web API, so genannte Formatter. Dabei unterscheidet MVC 6 zwischen InputFormatter und OutputFormatter. Erstere kümmern sich um das Deserialisieren von eingehenden Daten. Ein Beispiel dafür ist das Umwandeln von JSON-basierten Informationen in Objekte. Letztere kümmern sich hingegen um das Serialisieren von ausgehenden Daten, beispielsweise das Umwandeln von Objekten in ein JSON-Dokument. Sämtliche Input- und OutputFormatter verwaltet MVC 6 in einer Auflistung. Immer, wenn es Daten zu (de-)serialisieren gilt, durchsucht MVC 6 diese Auflistungen nach einem passenden Formatter und zieht ihn heran. Die Auswahl erfolgt dabei anhand des Typs des vorherrschenden Objekts sowie anhand des MIME-Type des gewünschten Datenformats.

Standardmäßig finden sich in den genannten Auflistungen Formatter, die sich um die Arbeit mit JSON kümmern. Sie nennen sich JsonInputFormatter und JsonOutputFormatter und basieren auf dem populären Open-Source-Projekt Json.NET [1]. Die Auflistung der Output Formatter beinhaltet in der hier betrachteten Beta 3 darüber hinaus zwei weitere standardmäßig eingerichtete Einträge: Der StringOutputFormatter kümmert sich um das Verarbeiten von Ergebnissen, die lediglich aus einem String bestehen. Die Aufgabe des HttpNoContentFormatters ist es, den HTTP-Statuscode auf 204 (NO CONTENT) zu setzen, falls keine Antwort vorliegt. Das ist bei Operationen, die den Rückgabewert void aufweisen, der Fall.

Formatter konfigurieren

Um die (De-)Serialisierung zu beeinflussen, kann der Entwickler beim Start der Anwendung die standardmäßig eingerichteten Formatter konfigurieren bzw. die genannten Auflistungen manipulieren, sprich weitere Formatter hinzufügen oder bestehende entfernen. Ein Beispiel dafür findet sich in Listing 2.1. Es zeigt die Methode ConfigureServices der Klasse Startup, die sich in jedem ASP.NET-MVC-6-Projekt befindet und die Webanwendung beim Hochfahren initialisiert. Die Aufgabe von ConfigureServices ist es, austauschbare Komponenten über den Dependency-Injection-Mechanismus von ASP.NET zur Verfügung zu stellen. Diese Komponenten, die sich auch Services oder Dienste nennen, hinterlegt ConfigureServices in einer vom Webserver übergebenen Auflistung des Typs IServiceCollection.

Zu diesen Komponenten zählen auch die Services, auf die sich ASP.NET MVC stützt. Die Erweiterungsmethode AddMvc fügt sie hinzu. Die Methode Configure gibt dem Entwickler die Möglichkeit, die hinzugefügten Komponenten zu konfigurieren. Dazu führt er als Typparameter den Typ der Komponente an, über die Konfigurationsoptionen festzulegen sind. Im Fall von ASP. NET MVC nennt sich diese Komponente MvcOptions. Der erste Parameter dieser Methode ist ein Lambda-Ausdruck, der eine Instanz dieser Komponente entgegennimmt und sie konfiguriert.

Listing 2.1 durchforstet die Auflistung InputFormatters, um den standardmäßig vorherrschenden JsonOutputFormatter zu finden. Dabei ist zu beachten, dass die Auflistung OutputFormatterDescriptor Objekte, die – wie der Name schon vermuten lässt, OutputFormatter beschreiben – beinhaltet. Über ihre Eigenschaft Instance verweisen diese Objekte auf den jeweiligen Formatter. Daher findet im betrachteten Fall auch mit Select eine Projektion auf diese Eigenschaft statt. Die LINQ-Methode OfType filtert anschließend nach dem gewünschten Typ, und FirstOrDefault liefert ein einzelnes Objekt retour. Damit diese LINQ-Methoden zur Verfügung stehen, ist der Namensraum System.Linq einzubinden.

Der auf diesem Weg ermittelte JsonOutputFormatter bietet sich über seine Eigenschaft ReferenceLoopHandling ein Konfigurationsobjekt an. Um die Arbeit mit diesem Objekt zu veranschaulichen, setzt das betrachtete Listing dessen Eigenschaft ReferenceLoopHandling auf Ignore. Das hat zur Folge, dass der Formatter Zyklen in den zu serialisierenden Objektgraphen ignoriert. Ein solcher Zyklus ergibt sich zum Beispiel, wenn zwei Objekte gegenseitig aufeinander verweisen. Gerade beim Einsatz von Entitäten mit bidirektionalen Beziehungen ist dies häufig der Fall. Der Standardwert von ReferenceLoopHandling nennt sich Error. Diese Einstellung bewirkt, dass der Formatter beim Vorfinden eines Zyklus eine Ausnahme auslöst.

Der Vollständigkeit halber wiederholt das betrachtete Listing dieselben Schritte für den JsonInputFormatter. Informationen über die vielen zur Verfügung stehenden Konfigurationsoptionen finden sich unter [1].

Formatter für XML einrichten

Im Lieferumfang von MVC 6 befinden sich auch Formatter für die Arbeit mit XML. Die Formatter XmlDataContractSerializerOutputFormatter und XmlDataContractSerializerInputFormatter verwenden dazu den aus der Welt von WCF bekannten DataContractSerializer. Mit dem XmlSerializerOutputFormatter und XmlSerializerInputFormatter liegen ergänzend dazu zwei Alternativen vor, die sich nicht des DataContractSerializers bedienen, sondern auf den älteren, seit den ersten Tagen von .NET vorliegenden XmlSerializer zurückgreifen.

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().Configure<MvcOptions>(options =>
{
var jsonOutput = options
.OutputFormatters
.Select(d => d.Instance)
.OfType<JsonOutputFormatter>()
.FirstOrDefault();

jsonOutput.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore;

var jsonInput = options
.InputFormatters
.Select(d => d.Instance)
.OfType<JsonInputFormatter>()
.FirstOrDefault();

jsonInput.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore;

}
}

Listing 2.1

Da diese Formatter standardmäßig nicht eingerichtet sind, muss der Entwickler sie innerhalb der in Listing 2.1 gezeigten Methode ConfigureServices zu den Auflistungen OutputFormatters und InputFormatters hinzufügen:

var xmlOutput = new XmlDataContractSerializerOutputFormatter();
options.OutputFormatters.Add(xmlOutput);
var xmlInput = new XmlDataContractSerializerInputFormatter();
options.InputFormatters.Add(xmlInput);

Eigenen I...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang