Umstieg auf .NET Core, Teil 4: SOAP- und REST-Webservices umstellen

Seite 2: Zwei Migrationswege für WebAPIs

Inhaltsverzeichnis

Zu den WebAPIs führen zwei unterschiedlich lange Wege: Der erste ist der kürzere, er vermeidet viele Code-Änderungen.

Microsoft bietet ein Kompatibilitätspaket Microsoft.AspNetCore.Mvc.WebApiCompatShim an, mit dem die alte Basisklasse ApiController sowie in der klassischen WebAPI übliche Nachrichtenklassen wie HttpRequestMessage und HttpResponseMessage zur Verfügung stehen. Auch die Regel für Routing und Parameterbindung entsprechen mit diesem Paket der klassischen WebAPI.

Der zweite Weg, ohne das Kompatibilitätspaket, ist länger, weil mehr Programmcodeänderungen ) notwendig sind, führt aber zu WebAPIs, die dem neuen Standard in .NET Core entsprechen. Notwendige Änderungen betreffen die Basisklasse für Controller; sie ist nicht mehr ApiController, sondern Microsoft.AspNetCore.Mvc.ControllerBase. Ebenso ist der Rückgabetyp der Aktionsmethoden nicht mehr die Schnittstelle IHttpActionResult, sondern die Klasse ActionResult<T>. Verweise auf nicht mehr existierende Namensräume wie System.Web.Http sind zu löschen. Außerdem muss man das Routing (die zu einem Controller führende URL sowie das HTTP-Verb) mit den Annotationen, wie [Route], [HttpGet], [HttpPost], [HttpPut], [HttpDelete] usw. festlegen.

Eine weitere Herausforderung sind die Änderungen des JSON-Serializers. Microsoft verwendet seit ASP.NET Core 3.0 nicht mehr das in .NET Framework und .NET Core seit Jahren bevorzugte JSON.NET (alias Newtonsoft JSON), sondern hat mit System.Text.Json eine neue eigene Bibliothek für JSON-Verarbeitung implementiert, die höhere Performance verspricht. Im Leistungstest ist System.Text.Json etwas performanter als JSON.NET, allerdings lassen sich die vom Entwicklungsteam verkündeten Geschwindigkeitszuwächse von 1,5- bis zweifach für Serialisierung und Deserialisierung bisher nicht verifizieren (s. Abb. 2).

Leistungstest von System.Text.Json im Vergleich zu JSON.NET mit verschiedenen JSON-Dokumentgrößen (Abb. 2)

Allerdings ist System.Text.Json gegenüber JSON.NET funktional eingeschränkt. Microsoft bietet dazu eine längere Vergleichstabelle. Der neue Serializer unterstützt zum Beispiel nicht die Datentypen BigInteger, TimeSpan, TimeZoneInfo, DBNull, ValueTuple, ExpandoObject, DataTable und DataRow.

Zahlreiche Verhaltensunterschiede im Detail finden sich insbesondere auch hinsichtlich der Strenge der Dateninterpretation. Dazu ein Beispiel: Während JSON.NET ein Datum auch in den Formen

2019-07-15T15:04:05.00+0100

und

2019-07-15T15:04:05.000+01:00

akzeptiert, gelingt eine Deserialisierung bei System.Text.Json allein mit dem Format

2019-07-15T15:04:05.000+01:00.

Diese Verhaltensunterschiede können dazu führen, dass WebAPIs beim Wechsel von der klassischen ASP.NET WebAPI zu ASP.NET Core WebAPI beziehungsweise ASP.NET Core WebAPI 1.x/2.x zu ASP.NET Core WebAPI 3.x nicht mehr wie gewohnt funktionieren.

Mögliche Inkompatibilitäten waren der Grund, warum James Newton-King, der Autor von JSON.NET, sich der vom .NET-Entwicklungsteam gewünschten inneren Umgestaltung von JSON.NET verweigert hat. Zum Glück können Entwickler auch eine ASP.NET Core 3.x-basierte WebAPI wieder auf JSON.NET zurückschalten, in dem sie in der Startup-Klasse die Methode services.AddMvc().AddNewtonsoftJson() aus dem neuen NuGet-Paket Microsoft.AspNetCore.Mvc.NewtonsoftJson aufrufen.

Zu den genannten Aufwänden kommt bei der üblichen Nutzung von Webserver-APIs (bspw. Request- und Response-Header, Sessions, Caching, Authentifizierung) noch der Umstellungsaufwand hinzu, der schon in Teil 3 der Migrationsserie beschrieben wurde und nicht nur Websites, sondern auch Web-APIs betrifft. Auch die allgemeinen Änderungen in den Basisklassen schlagen bei einer Migration von .NET Framework zu .NET Core bei den WebAPIs wieder durch (vgl. Teil 2).

Microsoft, einst ein Vorreiter bei der Spezifikation und Implementierung von SOAP (vier der acht Autoren der SOAP-1.1-Sepzifikation waren bei Microsoft angestellt, ein fünfter wechselte kurz danach zu diesem Hersteller), hat sich von diesem Protokoll weitgehend verabschiedet.

Verwirrend ist für viele Benutzer die Situation um WCF in .NET Core. Seit WCF 2015 Open Source wurde, gibt es ein GitHub-Repository für WCF auf .NET Core, das aber nur den Client-Teil von WCF enthält. Der erste Satz darin verdeutlicht es: "This repo contains the client-oriented WCF libraries that enable applications built on .NET Core to communicate with WCF services." Im weiteren Text stellt der Anbieter dann auch noch klar, dass es sich nur um eine Teilmenge der WCF-Funktionen handelt.

Die serverseitigen Bibliotheken von WCF, die auf einem Application Server benötigt würden, gibt es nicht in dem Repository. Auf GitHub wurde zwei Jahre lang hart über "Server Side WCF" diskutiert. Auf der Build-Konferenz im Mai 2019 machte Microsoft dann deutlich: Die Übernahme von Klassen aus dem klassisches .NET Framework nach .NET Core ist nun abgeschlossen und WCF-Server gehören zu den Techniken, die Microsoft nicht mehr auf .NET Core portieren will.

Immerhin hat Microsoft den übrigen, bisher nicht portierten WCF-Quellcode freigegeben und fördert per Ankündigung vom 7. Juni 2019 die Portierung von WCF durch die "Community" über die .NET Foundation.

Das Projekt heißt Core WCF und ist laut Aussage auf der Website noch nicht einsatzreif: "Please note that right now, this port is not production ready.". Bis zur Veröffentlichung dieses Beitrags lag noch kein einziges Release in dem Projekt vor. Das definierte erste Ziel ist auch nicht die vollständige Kompatibilität zum klassischen WCF, sondern SOAP-Dienste via TCP und HTTP anbieten zu können. Die deutlich performantere binäre Serialisierung bleibt – zumindest vorerst – außen vor.

Die in .NET Core existierende WCF-Clientseite ist vielfältiger aufgestellt. Mit Ausnahme der nachrichtenbasierten Sicherheit mit WS-Security und einigen Windows-spezifischen Authentizierungsfeatures auf Linux und macOS sind alle Funktionen plattformneutral vorhanden.

Dennoch stellt sich die berechtigte Frage, ob man nicht nur darauf vertrauen darf, dass die Macher von Core WCF das Projekt jemals auf einen praxisreifen Stand bringen werden, sondern auch, ob sie gewillt sind, in Zukunft den Programmcode immer wieder an die Änderungen in den kommenden .NET-Versionen anzupassen. .NET 5.0 soll im November 2020 als Nachfolger von .NET Core 3.1 erscheinen. Danach gibt es jedes Jahr im November eine neue Hauptversion (.NET 6.0, .NET 7.0, .NET 8.0 usw.). Gemäß dem von Microsoft verfolgten Konzept des Semantic Versioning sind Breaking Changes in den Hauptversionen möglich und diese hat das Unternehmen beim Wechsel von .NET Core 1.x zu 2.0 und 2.x zu 3.0 auch zahlreich einfließen lassen. Sogar der Wechsel von .NET Core 3.0 zu 3.1 brachte Breaking Changes, die es eigentlich nicht hätte geben dürfen.

Für Core WCF bedeutet das jedoch, dass es auch in Zukunft immer wieder an die .NET-Hauptversionen angepasst werden muss. Das Problem lässt sich nur mildern, wenn man gewillt ist, bei Bedarf den Quellcode von Core WCF selbst anzupassen.