Sie sind hier: Weblog

Web APIs mit ASP.NET MVC 6: Serialisierung mit Formatter beeinflussen

Foto ,
14.03.2015 10:01:00

Um die (De)Serialisierung bei ASP.NET MVC 6 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 im nachfolgenden Listing. Es zeigt die Methode ConfigureServices der Klasse Startup, welche sich in jedem ASP.NET-MVC-6-Projekt befindet und die Web-Anwendung 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, welche sich auch Services oder Dienste nennen, hinterlegt ConfigureServices in einer vom Web-Server übergebenen Auflistung des Typs IServiceCollection.

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

Listing 1 durchforstet die Auflistung InputFormatters um den standardmäßig vorherrschenden JsonOutputFormatter zu finden. Dabei ist zu beachten, dass die Auflistung OutputFormatterDescriptor-Objekte, welche – wie der Name schon vermuten lässt, OutputFormatter beschreiben – beinhaltet. Über ihre Eigenschaft Instance verweisen diese Objekte auf den jeweiligen Formatter. Deswegen 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 Konfigurations-Objekt 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].

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;

    }
}

[1] http://www.newtonsoft.com/json