RESTful Web Services mit .NET und ExtJs: Service-Hosting

Dieser Artikel ist Teil 4 einer mehrteiligen Serie, die sich mit dem Erstellen und Nutzen eines RESTful Web Service mit Hilfe von .NET und ExtJs beschäftigt.

Ein WCF-Service läuft nicht als eigenständiges Programm. Der Normalfall wird sein, dass ein Programm auf den konfigurierten Endpunkten lauscht, und sobald ein passender Request eines Clients angeschwemmt wird, eine Instanz der WCF-Service-Klasse erstellt und ihr die richtigen Parameter übergibt. Der Service befindet sich also in einer Umgebung, die weiß, wie sie zu lauschen hat, und die weiß, von welcher Klasse der Service ist, und wie er zu erzeugen ist. Diese Umgebung ist der ServiceHost, und um den passenden ServiceHost für unseren WCF-Service geht es im viertel Teil meiner Serie.

Wie überall in .NET, gibt es zwei Möglichkeiten, die Dinge anzugehen: die einfache Variante, die sich stark auf Konfiguration verlässt, oder die Variante, alles per Code selbst zu machen. Die einfache Variante, einen ServiceHost zu starten, ist wie folgt:

using (ServiceHost serviceHost = new ServiceHost(typeof(ServiceImplementationClass)))
{
   serviceHost.Open();
   Console.WriteLine("The service is ready.");
   Console.WriteLine("Press  to terminate service.");
   Console.ReadLine();
}

Dieser Codeschnipsel kann in jeder Anwendung eingefügt werden – sei es eine Konsolenanwendung, ein Windows-Dienst, eine WPF-Applikation oder was auch immer. Hauptsache, ausführbar. Welches Protokoll verwendet wird, wie die URI ist, auf der gelauscht wird, und all die anderen Einstellungen passieren werden dabei im system.serviceModel-Abschnitt der Konfigurationsdatei der Anwendung festgelegt.

ServiceHosts sind, wie zu sehen ist, an sich unabhängig von der Klasse des Services, dem sie eine Umgebung bieten. Dagegen muss man beim obigen Ansatz fest programmieren, welcher Service gehostet werden soll – nicht sehr gut wiederverwendbar in anderen Projekten. Wenn man mal darüber nachdenkt, liegt es also recht nahe, eine Factory-Klasse zu schreiben, die anhand einer Service-Klasse den passenden ServiceHost zurückliefert. Nun ist es nicht sehr überraschend, dass im .NET-Framework so eine Factory-Infrastruktur bereits vorhanden ist.

Die Factory-Klasse für ServiceHosts nennt sich – wieder keine wirkliche Überraschung – ServiceHostFactory und kann für beliebige Familien von ServiceHosts so überschrieben werden, wie das notwendig erscheint. Dabei gibt es bereits einige Implementierungen für verschiedene Szenarien: unter anderem auch das Szenario eines Webservice, das wir benötigen, nämlich WebServiceHostFactory. Die MSDN bietet einen kleinen, sehr treffenden Satz, der diese Klasse beschreibt:

A factory that provides instances of WebServiceHost in managed hosting environments where the host instance is created dynamically in response to incoming messages.

REST-Services sind nicht zuletzt, weil sie sich auf HTTP verlassen, natürlich prädestiniert dafür, im Kontext eines Webservers zu laufen (man könnte so weit gehen zu behaupten, dass sie nur dort einen Sinn ergeben). Unser REST-Web-Service wird also von einer WebServiceHost-Umgebung gehostet, die wiederrum von einer WebServiceHostFactory erzeugt wird. Wir haben die Wahl der Anwendung, die diese Klassen in ihrem ausführbaren Part benutzt. Wir werden später sowieso noch eine Webanwendung brauchen: sie soll ja unseren Client darstellen, der per Javascript auf den Service zugreift. Daher lassen wir unseren Service einfach gleich mit vom IIS hosten.

Das bietet uns noch einen weiteren Vorteil. Sagen wir, unsere Webseite (der Client) läuft später unter der Adresse

http://localhost/MyServiceClient/

(also auf Port 80). Dann müsste unser Service so konfiguriert werden, dass er auf derselben Adresse auf irgendeinem anderen Port lauscht – 80 ist bereits vom IIS besetzt. Das wiederum hätte alllerdings zur Folge, dass das Javascript auf localhost:80 zugreifen muss auf einen Service, der auf localhost:1223 (beliebiger anderer Port) lauscht. Und das wiederum eröffnet eine ganze Reihe von potentiellen Problemen, die darin begründet sind, dass Javascript (aus Sicherheitsgründen) nicht einfach auf Drittressourcen ungeprüft zugreifen können darf – Stichwort XSS.

Diesen ganzen Ärger umgehen wir, indem wir eine Webanwendung erstellen, und den Service innerhalb dieser Webanwendung hosten lassen.

Alles, was dazu nötig ist, ist eine Datei „MessageService.svc“ mit folgendem Inhalt:

<%@ ServiceHost 
  Language="C#" 
  Service="MessageService.MessageService"  
  Factory="System.ServiceModel.Activation.WebServiceHostFactory" 
%>

That’s it. Die Angabe beim Parameter „Service“ bezieht sich dabei auf den vollen Namen (Namespace + Klasse) der Service-Implementierung. Wenn die Webanwendung gestartet wird und die Adresse http://localhost:PORT/Webanwendungsname/ExampleService.svc im Browser aufgerufen wird, sollte bereits eine Antwort erfolgen – „Es wurde kein Endpunkt gefunden.“, was logisch ist, da keiner unserer Schnittstellenoperationen auf „/“ zugeordnet wurde.

Weiter geht’s im nächsten Teil mit der Programmierung des Zugriffs auf den neuen Service per Javascript.

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: