0 Minuten Lesezeit

Teile den Artikel!

In meiner Serie zum Erstellen von Web APIs mit Azure Functions stelle ich neben einigen Pattern auch Codebeispiele vor. In Summe sollen diese Beiträge als Handlungsanweisung dienen, um effizient Web APIs mit Azure Functions zu erstellen.

Hier nochmal eine Übersicht der bisher veröffentlichten Beiträge:

Überblick

Nachdem ich im zweiten Teil eine Erweiterung zum Requesthandling vorgestellt habe, möchte ich in diesem Beitrag auf das Response-Handling eingehen. Hierzu möchte ich die bestehende Extension aus dem letzten Beitrag nutzen und eine generische Lösung bereitstellen, wie Antworten einer Web API mit Azure Functions einfach erstellt werden können.

Response Handling in Azure Functions

Wenn eine Function einen Response sendet, beinhaltet die Antwort i.d.R. folgende Komponenten:

  • Header-Parameter
  • Contenttype (spezieller Header)
  • Http-Statuscode
  • Content

Das bedeutet abhängig von der vorgenommenen Aktion (GET, PUT, DELETE usw.) erhält der Aufrufer neben dem Inhalt auch einen entsprechenden Http-Statuscode, der dem Aufrufer über den Erfolg, oder Misserfolg des Aufrufs mitteilt.

 

Fluent Builder Pattern

Für die Erzeugung von neuen Objekten verwenden Entwickler für gewöhnlich (Klassen-) Konstruktoren, sodass Parameter korrekt zugewiesen werden.

Für unser Szenario der Erstellung eines Response-Objekts ist eine mögliche Implementierung der HttpResponse-Klasse im Folgenden dargestellt:

Copy to Clipboard

Bei diesem Beispiel wird sofort klar, eine Erzeugung eines HttpResponse-Ojbekt ist mit einem größeren Aufwand verbunden, da zum einen sämtliche Informationen zum Zeitpunkt der Erzeugung des Response-Objekts vorliegen müssen und zum anderen die Leserbarkeit beim Aufruf leidet.

Beispielhafter Aufruf:

Copy to Clipboard

In C# kann durch die Verwendung von statischen Extension-Methoden (ähnlich zu den Request-Handling-Methoden aus dem letzten Beitrag) das Fluent Builder Pattern angewandt werden.

Das Fluent Builder Pattern hilft dabei die Logik zur Erstellung eines Objekts in einen Builder zu extrahieren. Hierbei ist der Builder für die Instanziierung der Klasse zuständig. Dadurch wird die Lesbarkeit und Einfachheit des erstellen Codes erhöht. Ein weiterer Vorteil wäre, dass der Aufrufer der Builder-Methoden lediglich die konkreten Werte übergibt.

Der obige Aufruf würde unter der Verwendung des Fluent Builder Pattern exemplarisch so aussehen:

Copy to Clipboard

Erweiterung Extension

Die bestehende Extension soll für das Response-Handling verwendet und erweitert werden. Hierzu wird die Implementierung in zwei Teile unterteilt:

  • Builder: in einem neuen Typ (HttpResponse) werden die benötigten Informationen gehalten. Dieser Typ wird durch die Verwendung von Builder-Methoden in einer separaten Builder-Klasse erzeugt.
  • Response Handling: die bestehende Extension zum Konvertieren von Requests wird um weitere Funktionalität erweitert. Hierzu gehören Methoden, welche das Builder-Objekt befüllen und hierüber das Zielobjekt HttpResponse erzeut. Diese Klasse soll auch das Senden von einem erfolgreichen wie auch fehlerhaften (Exception) Response ermöglichen.

Builder

Das Basis-Objekt für die Builder-Klasse stellt den Response dar. Im Microsoft.AspNetCore.Mvc-Namespace bietet C# (u.a. mit .Net Core 3.1) die Klasse ContentResult zur Verfügung. Diese erbt wiederum von der Klasse ActionResult und bietet bereits drei Properties, welche im HttpResponse verwendet werden sollen. Darüber hinaus kann hierdurch später einfach ein ActionResult aus der Azure Function zurückgegeben werden, was die Rückgabe generisch macht.

ContentResult stellt diese drei Eigenschaften bereit:

  • Content (string)
  • ContentType (string)
  • StatusCode (int)

Somit fehlt nur noch ein Dictionary aus Strings (IDictionary<string, string>) zur Repräsentation des Headers. Aus diesem Grund bietet es sich an, eine eigene Klasse zu erstellen, welche von ContentResult erbt und um die Header-Property erweitert wird.

Die Builder-Klasse besteht aus den Properties, welche später zur Erzeugung des HttpResponse-Objekts verwendet werden sollen. Daneben existiert noch eine Methode zur Ergänzung von Header-Einträgen und der Build-Methode, welche ein neues HttpResponse-Objekt erzeugt.

Responsehandler

Die bestehende Klasse HttpHandler wird um weitere Methoden erweitert werden. Diese sollen zum einen Funktionen bereitstellen, um das Builder-Objekt zu bestücken und zum anderen standardisierte Methoden zur Erstellung von Responses bereitstellen.

Um dem Nutzer Aufwand bei der Entwicklung zu ersparen, werden typische Einstellungen wie der Statuscode 200 und der Contenttype “application/json” als Standardwerte gesetzt. Somit muss der Aufrufer diese nicht jedes Mal erneut setzen, kann diese Werte aber zum Zeitpunkt des Aufrufes natürlich übergeben und dadurch die Werte entsprechend ändern.

Da die eigene Klasse HttpResponse von ContentResult abgeleitet wurde, entspricht der zurückgegebene Datentyp einem ActionResult. Dies entspricht dem Standardmäßigen Rückgabetyp von Azure Functions und muss somit nicht erneut gecastet werden, wenn ein Response über die Extension erzeugt wird.

Beispielhafte Implementierung

Im bestehenden GitHub-Repo aus dem letzten Beitrag wurde die Implementierung um das Response-Handling erweitert. Darin sind auch die bestehenden API-Endpunkte entsprechend erweitert worden.

Ein Beispielhafter Aufruf ist hier dargestellt:

Die Azure Functions können nun immer nach demselben Schema aufgebaut werden. Somit ist neben dem Request-Handling auch das Response- und Exception Handling abgebildet. Außerdem sieht man beim Response sofort, dass der entsprechende Statuscode gesetzt wurde, ohne dass dieser beim Aufruf explizit angegeben werden musste (siehe auch Screenshot von Postman).

Zusammenfassung

Die Nutzung der Extension hat nun einen Reifegrad erreicht, um bereits einfach und in einem größeren Umfeld Web APIs mit Azure Functions zu erstellen. Die Verwendung steigert die Effizienz der jeweiligen Implementierung ungemein und kann einfach verwendet werden.

Bevor APIs von außen verwendet werden können, benötigt der Aufrufer neben der URL des Endpunkts auch weitere Informationen (Query-Parameter, Http-Verb, usw.) für den Aufruf. Mit Swagger/ Open API besteht die Möglichkeit eine API-Definition für Aufrufer bereitzustellen. Unsere aktuelle Implementierung bietet diese Funktion aktuell noch nicht an. Die Verwendung von Swagger und der notwendigen Einstellungen werden im nächsten Blogbeitrag vorgestellt.

Waldemar Felde ist Berater und Entwickler bei Objektkultur. Er bewegt sich hauptsächlich im Microsoft 365 Umfeld, insbesondere im SharePoint-Bereich. Aber auch Integrationsthemen rund um Azure Functions, Logic Apps und Azure Service Bus nehmen einen sehr präsenten Platz bei ihm ein. Dabei steht die Umsetzung ganzheitlicher, effizienter wie auch effektiver Lösungen im Vordergrund.

Technische Entwicklungen werden stets mit Neugier verfolgt. Neuerungen werden direkt in kleinerem Umfeld begutachtet und ausprobiert.