WCF Wiederentdecken

Beliebt war WCF bei .NET-Multiplikatoren (also Blogger, Trainer und Evangelisten) gefühlt noch nie. Zu komplex und dann auch noch proprietär (pfui!). Beim Design von .NET Core hat sich wohl die interne Microsoft-Gruppe durchgesetzt, die auf Wellenlänger der .NET-Hipster war. Cross-Plattform für Linux und MacOS und volle Kanne Open-Source und in Sachen Verteilung natürlich REST!
WCF blieb dabei auf der Strecke, tja das W für Windows im Namen war hier für das Überleben hinderlich. Nichts gegen REST-Services. Gerade für öffentliche APIs haben sich diese aus guten Gründen gegen SOAP (ist das schon in Vergesseneit geraten?) durchgesetzt. Die Einstiegshürden sind recht gering. Man kann REST-Services aus allen Plattformen selbst mit Hausmitteln recht einfach ansprechen. Gerade für öffentliche APIs via Web scheint mir REST damit heutzutage das Bindemittel #1.

REST-Services in .NET mit WebAPI/MVC zu implementieren ist relativ leicht. Das hat Gründe im Design. Eigentlich bauen REST-Services auf wenig eigene Abstraktionen auf. Die Grundkonventionen werden von HTTP vorgegeben. Es gibt mit HTTP nur ein Transportprotokoll, mit SSL-Zertifikaten (was eigentlich heutzutage TLS heißt) eine primäre Sicherheitsarchitektur. Wenn das ein Softwareentwickler schwer zu verstehen findet, da kann der erfahrene WCF-Entwickler nur müde lächeln. In WCF gibt es verschiedene Transportprotokolle, bei denen jeweils bestimmte Features von WCF nicht oder nur unter bestimmten Bedingungen zur Verfügung stehen. WCF-Services können nicht nur auf eine Art konsumiert werden. Ein einmal geschriebener WCF-Service kann öffentlich via HTTP, im Netzwerk via TCP oder auf dem lokalen Recher mit Named Pipes und wahrscheinlich noch anderen Protokollen konsumiert werden, die nur WCF-Gurus kennen. Sicherheit kann auf Transportprotokollebene implementiert sein (eine komplizierte Abstraktion, die letztlich nur HTTPs meint) oder auf Nachrichtenebene, was einen von WCF selbst implementierten Mechanismus meint. Services können duplex sein, aber nicht mit einfachen HTTP-Bindings. Services können Session-basiert sein, aber nur wenn das Transportprotokoll es unterstützt. Dazu definiert man Service Contracts getrennt von den Service Implementierungen. Und warum ein Service überhaupt mehrere Service Contracts implementieren kann, habe ich auch noch in keinem realen Use-Case herausfinden können. Tja, nächster Punkt ist das Hosting. Auch hier ein Füllhorn an Möglichkeiten. IIS, Windows Service oder gar Self-Hosted in normaler Anwendungs-EXE? TCP-Binding in Windows-Service oder HTTP(s)-Binding in IIS klingt vernünftig. TCP-Binding in IIS geht aber auch und natürlich alles mit allem. WOW. Das muss man alles erstmal lernen. Und dann die Konfiguration. Jedes Parameterlein dieser ganzen Mächtigkeit einzeln austauschbar. Am besten alles in hässlichen XML-Konfigurationsdateien. Auch sehr witzig: Wenn man einmal große Datenmengen wie Binärdateien über WCF-Dienste übertragen will, gelten wieder andere Bedingungen. Ja, WCF ist wahnsinnig mächtig. Kompliziert auch.

Und dennoch, es hat auch heute seine Relevanz. Nein, nicht jedes Grüne-Wiese-Projekt sollte heute auf REST-Services setzten. WCF hat weiterhin einige unschlagbare Vorteile.
Und diese liegen – wie der Name sagt – im Bereich Windows. Aus dem Füllhorn der WCF-Features muss man sich die guten herauspicken! Unschlagbar ist für mich weiterhin die Möglichkeit auf einem lokalen Rechner einen Service via Local Pipe zu betreiben. Ist HTTP wirklich ein geeignetes Protokoll, um lokale Kommunikation zwischen Prozessen durchzuführen? Local Pipes sind ein optimales Protokoll für Machinen-lokale Kommunikation. HTTP wurde nun einmal für das WWW erfunden! Und darin ist es auch verdammt gut. Mit WCF hingegen hat man gerade innerhalb eines Netzwerkes eine große Flexibilität.

Und jetzt kommen wir zu einem wirklichen Produktivitätsvorteil: Symbolintegration. REST und auch SOAP oder gar historische Protokolle wie IDL basieren auf eigenen (Plattform-neutralen) Service-Schnittstellen. Bei REST ist diese nicht einmal offiziell standardisiert, wobei z.B. Swagger hier schon zu einer De-Facto-Standardisierung führt. WCF muss hingegen nicht zwingend Proxies via einer externen Schnittstellenbeschreibung (WCF nutzt auch WSDL von SOAP) generieren. Wenn der Client in .NET implementiert ist, kann auch das Konzept der Shared Contract DLL verwendet werden. Das ist 100% Symbolintegration! Für öffentliche Schnittstellen ist das nicht so relevant, da hier die Anforderung der Kompatibilität meist wichtig ist. Bei internen Schnittstellen, die auch gerade in der gleichen Solution liegen, kommt die Stärke der Symbolintegration aber voll zum Tragen. Eine Verweissuche von Server zu Client und ein einfaches Refactoring. Das geht mit Proxy-basierten Ansätzen nicht so leicht.

Und nein, WCF muss man nicht zwingend mit XML konfigurieren. Gerade wenn man viele Services nutzt, kann man die Konfiguration mittels Code und Konventionen aufsetzen. 100 Services erfordern nicht 100 Einzelkonfigurationen!

WCF kann sogar REST-Services publizieren. Aber dies wirkt immer wie ein Fremdkörper. Öffentliche APIs und interne APIs sind zwei komplett verschiedene Themengebiete, die vom API-Design anders aussehen sollten. Öffentliche APIs sollen meist von Entwicklern mit geringem Kenntnissstand verwendet werden können. Meist sind einige wenige, nach Verwendungsgebieten geordnete Services sinnvoll. Bei internen APIs ist nicht der Konsument wichtig, stattdessen sollte die Strukturierung für die interne Verständlichkeit im Vordergrund stehen. Und nein, somit macht es wenig Sinn eine bereits vorhandene API, die mittels WCF implementiert ist, mit etwas Konfiguration als REST-Service oder auch via SOAP extern bereitzustellen. Im Bereich .NET ist eine REST API am einfachsten mit WebAPI/MVC zu realisieren (ob .NET oder .NET Core – geschenkt), für eine interne API fährt man hingegen mit WCF weiterhin sehr gut. Ja, auch im Jahr 2017 und sicher auch die nächsten 10 Jahre!