Service Station

Eine Einführung in REST-Dienste mit WCF

Jon Flanders

Codedownload verfügbar in der MSDN-Codegalerie
Code online durchsuchen

Inhalt

Informationen zu REST
Ein abstraktes Beispiel
Warum Sie sich für REST interessieren sollten
WCF und REST
WebGetAttribute und WebInvokeAttribute
UriTemplate und UriTemplateTable
WebHttpBinding und WebHttpBehavior
WebServiceHost und WebServiceHostFactory
Verwenden des Beispielcodes

Dies ist der erste einer Reihe von Artikeln über das Erstellen von WCF-Diensten (Windows Communication Foundation) mit Hilfe des Architekturstils, der REST (Representational State Transfer) genannt wird. Man könnte sagen, dass 2009 hier in der Rubrik „Service Station“ das Jahr von REST ist. Meiner Meinung nach ist dies lange überfällig. REST ist seit seiner Einführung im Jahr 2000 ein beliebter Stil.

In diesem ersten Artikel sollen einige Grundsätze von REST erörtert und eine Implementierung eines REST-Diensts mithilfe von WCF präsentiert werden. In zukünftigen Artikeln wird ausführlicher auf die grundlegenden Gedanken von REST eingegangen sowie auf Technologien, die auf dieser Grundlage erstellt wurden.

Informationen zu REST

Ein Architekturstil ist eine Reihe von Einschränkungen, die beim Erstellen angewendet werden können. Mit einem Softwarearchitekturstil werden die Features beschrieben, mit denen eine Anleitung für die Implementierung eines Softwaresystems bereitgestellt werden kann. REST ist ein Architekturstil, mit dem Software erstellt werden kann, in der Clients (Benutzer-Agents) Anforderungen von Diensten (Endpunkten) durchführen können. REST ist eine Möglichkeit, einen Client-Server-Architekturstil zu implementieren. Es baut sogar ausdrücklich auf diesem Stil auf.

Den Begriff REST hat Roy Thomas Fielding in seiner PhD-Dissertation Architectural Styles and the Design of Network-based Software Architectures (Architekturstile und der Entwurf netzwerkbasierter Softwarearchitekturen) geprägt. Er war eine jener Personen, die an der Spezifikation dessen gearbeitet haben, was einen Großteil des Internets heutzutage in Betrieb hält: das Hypertext Transfer-Protokoll (HTTP). In der Regel ist der Hintergrund der Personen, die einen Architekturstil beschreiben, nicht wichtig für eine Besprechung des Stils. In diesem Fall halte ich es jedoch für wichtig, denn ich glaube, Sie erlangen dann am besten ein grundlegendes Verständnis von REST, wenn Sie an das Internet und dessen Funktionsweise denken.

Ich muss davon ausgehen, dass Sie als Entwickler mit dem Internet vertraut sind und es wahrscheinlich genau wie ich täglich stark nutzen. Das Internet kann wohl als die größte, skalierbarste und beliebteste verteilte Anwendung aller Zeiten betrachtet werden. Die Einschränkungen von REST beruhen auf den gleichen zugrunde liegenden Prinzipien, die das Internet regulieren. Diese Prinzipien sind Folgende:

  • Benutzer-Agents interagieren mit Ressourcen, und Ressourcen sind alles, was benannt und repräsentiert werden kann. Jede Ressource kann über einen eindeutigen URI (Uniform Resource Identifier) angesprochen werden.
  • Die Interaktion mit Ressourcen (die anhand ihrer eindeutigen URIs gefunden werden) wird durch die Verwendung einer einheitlichen Schnittstelle der HTTP-Standardverben erreicht (GET, POST, PUT und DELETE). Ebenfalls wichtig in der Interaktion ist die Deklaration des Medientyps der Ressource, der mithilfe des HTTP-Content-Type-Headers bestimmt wird. (XHTML, XML, JPG, PNG und JSON sind einige bekannte Medientypen.)
  • Ressourcen sind selbstbeschreibend. Alle Informationen, die zum Verarbeiten einer Anforderung für eine Ressource erforderlich sind, sind in der Anforderung selbst enthalten. (Dadurch können Dienste statusfrei sein.)
  • Ressourcen enthalten Links zu anderen Ressourcen (Hypermedia).

Ein abstraktes Beispiel

Ein Dienst, der den REST-Architekturstil verwendet, wird im Allgemeinen als REST-Dienst oder -Endpunkt bezeichnet. Um ein Gefühl für die diesem Architekturstil zugrunde liegenden Prinzipien zu bekommen, möchte ich ein kleines Beispiel vorstellen. Stellen Sie sich vor, es müsste ein Dienst erstellt werden, der mit den Daten hinter dem MSDN Magazin arbeitet, ein Dienst, der mitteilen könnte, seit wie vielen Jahren das MSDN Magazin veröffentlicht wird, und der jeden Artikel in jeder Ausgabe nennen kann. Die Anforderung besteht darin, dass die Herausgeber des Magazins mit diesem Dienst neue Artikel hinzufügen und Daten für bevorstehende Ausgaben verwalten können.

Beim Erstellen von REST-Diensten können Sie einen sehr einfachen Satz grundlegender Schritte durchlaufen, um Ihren Dienst zu entwickeln:

  1. Welches werden Ihre Ressourcen sein?
  2. Mit welchen URIs werden diese Ressourcen repräsentiert?
  3. Welche Bestandteile der einheitlichen Schnittstelle (HTTP-Verben) werden von den einzelnen URIs unterstützt?

Dies sind die grundlegenden Bausteine eines REST-Endpunkts: Ressourcen und ihre Darstellungen, URIs für diese Ressourcen und die Bestandteile der einheitlichen Schnittstelle, auf die jeder URI reagiert. Es gibt fortschrittlichere Features, die Sie nutzen können, z. B. die explizitere Verwendung von Statuscodes sowie von Hyperlinks zum Verwalten des Ressourcenstatus, aber in diesem Beispiel bleibe ich bei den Grundlagen.

Anhand dieser Schritte kann der hypothetische Dienst entworfen werden. Die Ressourcen sind alle Jahre, in denen das MSDN Magazin herausgegeben wurde, alle Ausgaben, die jedes Jahr veröffentlicht wurden, sowie alle Artikel, die in jedem Magazin enthalten sind. Für dieses besondere Beispiel wird der Medientyp „application/xml“ (XML) verwendet, um diese Ressourcen zu repräsentieren. Es muss aber bedacht werden, dass REST-Dienste in keinster Weise auf XML als Medientyp begrenzt sind.

Als Nächstes müssen die URIs für jede Ressource bestimmt werden. Im Augenblick müssen nur die relativen URIs bestimmt werden, da der absolute URI davon bestimmt wird, wo der Endpunkt gehostet wird. Die Liste der Jahre ist der Stamm-URI des Diensts (/). Bei dieser Syntax werden mit „/{Jahr}“ alle Ausgaben für die einzelnen Jahre zurückgegeben. „/{Jahr}/{Ausgabe}“ ist der URI für die einzelnen Ausgaben (jede Ausgabe wird anhand ihres Veröffentlichungsmonats identifiziert), und mit „/{Jahr}/{Ausgabe}/{Artikel}“ werden die einzelnen Artikel repräsentiert. Dabei wird davon ausgegangen, dass die Artikel in allen Ausgaben von 1 bis n nummeriert sind.

Danach folgt die Zuordnung von URIs zu einer einheitlichen Schnittstelle. Da der Verlauf des Magazins wirklich schreibgeschützt sein sollte, macht die Stammressource nur GET verfügbar. Ein neues Jahr kann dem URI „/{Jahr}“ mit einem PUT hinzugefügt werden. Mit PUT werden neue Ressourcen erstellt, wenn der URI der neuen Ressource dem Client bekannt ist, so wie in diesem Fall. Mithilfe von PUT können vorhandene Ressourcen auch aktualisiert werden, wenn der URI bekannt ist. Mit POST wird eine Ressource erstellt, wenn der URI der neuen Ressource dem Client nicht bekannt ist. Beim Hinzufügen einer neuen Artikelressource wird also das Verb POST verwendet, das an den URI „/{Jahr}/{Ausgabe}“ gesendet wird.

So kann mit jeder Ressource und jedem Verb verfahren werden, aber hoffentlich haben Sie ein Gefühl für die Schritte entwickelt, die Sie durchlaufen müssen, um das Design eines REST-Endpunkts zu bestimmen. Die vollständige Liste der Ressourcen, URIs und Verben sehen Sie in Abbildung 1.

Abbildung 1 Betriebssystemunterstützung
Ressource URI Verben
Alle Jahre "/ " GET
Die Ausgaben eines bestimmten Jahres „/{Jahr}“ GET, PUT
Eine bestimmte Ausgabe „/{Jahr}/{Ausgabe}“ GET, PUT
Ein Artikel „/{Jahr}/{Ausgabe}/{Artikel}“ GET, POST (die Artikelnummer wird vom System zugewiesen), PUT, DELETE (Löschen wird deaktiviert, sobald ein Artikel veröffentlicht wurde)

Wenn ich die Artikel vom Januar 2006 als Client nutzen möchte, führe ich ein HTTP GET zu „/2006/January“ durch. Wenn ich Herausgeber wäre und einen Artikel der Ausgabe vom Dezember 2008 hinzufügen möchte, würde der Client mit POST eine Artikelressource zu „/2008/December“ und damit einen neuen Artikel zu dieser Ausgabe hinzufügen. Dieses Muster würde ich immer wieder verwenden, um diesen Dienst als Client nutzen zu können.

Warum Sie sich für REST interessieren sollten

Da Sie jetzt ein wenig über REST wissen, fragen sich Sie wahrscheinlich, warum Sie sich dafür interessieren sollten. Als Entwickler benötigen Sie Motivation zum Lernen, um sich einen Stil, eine Technologie oder ein Muster anzueignen. Wenn Sie dieses Magazin lesen, sind Sie wahrscheinlich ein Entwickler von Microsoft-Technologie. Zum Implementieren von Client-Server-Anwendungen haben Sie wahrscheinlich einen anderen Architekturstil verwendet: RPC (Remoteprozeduraufruf). Unabhängig davon, ob Sie proprietäre RPC-Systeme wie DCOM oder .NET Remoting oder interoperable RPC-Technologien wie SOAP mittels ASMX oder WCF verwendet haben: Dies sind die Implementierungen des Client-Server-Stils, den wir auf der Microsoft-Plattform hatten. Warum sollten Sie also lernen, REST zu verwenden?

Dafür gibt es zwei Hauptgründe. Erstens bietet REST in vielen Fällen einige bedeutsame Features und Vorteile gegenüber RPC-Technologien. Zweitens verschiebt Microsoft viele seiner eigenen Implementierungen von RPC-Technologien (z. B. SOAP) nach REST. Das bedeutet, selbst wenn Sie nicht überzeugt oder motiviert sind, Ihre eigenen Systeme mit REST zu erstellen, müssen Sie wissen, wie Sie damit interagieren können, da sich immer mehr Frameworks und Technologien von Microsoft (und anderen) nach REST verlagern.

Hier eine (nicht vollständige) Liste weiterer Vorteile:

Zwischenspeichern Wenn REST-Endpunkte mithilfe von HTTP nach Daten abgefragt werden, wird das HTTP-Verb GET verwendet. Es gibt viele verschiedene Möglichkeiten, Ressourcen zwischenzuspeichern, die in Reaktion auf eine GET-Anforderung zurückgegeben werden. Bedingtes GET ist eine Möglichkeit, mit der ein Client mithilfe des Diensts prüfen kann, ob seine Version der Daten immer noch aktuell ist. Dies ist ein optionales Implementierungsdetail, das von einem REST-Endpunkt implementiert werden kann, um Geschwindigkeit und Skalierbarkeit weiter zu verbessern.

Ausskalieren REST bestärkt jede Ressource darin, alle Status zu enthalten, die erforderlich sind, um eine bestimmte Anforderung zu verarbeiten. REST-Dienste sind viel einfacher auszuskalieren, wenn sie diese Einschränkung erfüllen und statusfrei sein können.

Nebenwirkungen REST-Dienste sollten keine Nebenwirkungen haben, wenn Sie mithilfe von GET um eine Ressource bitten. Leider ist diese Einschränkung einfacher zu unterlaufen als einige der anderen REST-Einschränkungen.

Idempotenz Die anderen beiden wichtigen HTTP-Verben, die in der Regel als Bestandteil der einheitlichen Schnittstelle verwendet werden, sind PUT und DELETE. PUT wird am häufigsten verwendet, wenn ein Benutzer-Agent eine Ressource ändern möchte. DELETE ist selbstbeschreibend. Die wichtige Eigenschaft, die mit dem Wort „Idempotenz“ beschrieben wird, ist, dass Sie diese beiden Verben mehr als einmal auf eine bestimmte Ressource anwenden können. Die Ergebnisse sind mit jenen bei der ersten Verwendung identisch. Zumindest gibt es keine weiteren Auswirkungen. Das ist beruhigend beim Erstellen zuverlässiger verteilter Systeme, in denen Fehler, Netzwerkfehler oder Wartezeiten bewirken können, dass Code mehrmals ausgeführt wird.

Interoperabilität Viele Personen halten SOAP für die interoperabelste Möglichkeit, Client-Server-Programme zu implementieren. Aber einige Sprachen und Umgebungen haben immer noch keine SOAP-Toolkits. Andere, die Toolkits haben, basieren auf älteren Standards, die nicht immer mit Toolkits kommunizieren können, mit denen neuere Standards implementiert werden. REST erfordert für die meisten Vorgänge lediglich die Verfügbarkeit einer HTTP-Bibliothek (eine XML-Bibliothek ist selbstverständlich oft ebenso nützlich), und es ist sicherlich interoperabler als jede RCP-Technologie, einschließlich SOAP.

Einfachheit Dieser Vorteil ist subjektiver als die anderen und kann für verschiedene Personen unterschiedliche Bedeutungen haben. Für mich besteht die Einfachheit der Verwendung von REST in URIs, mit denen die Ressourcen und die einheitliche Schnittstelle repräsentiert werden. Als erfahrener Websurfer kann ich verschiedene URIs in meinen Browser eingeben, um verschiedene Ressourcen abzurufen. Dies wird manchmal als URI- oder URL-Hacken bezeichnet, ist aber in keiner Weise ruchlos. Aufgrund dieser Erfahrung beim Verwenden von URIs über viele Jahre hinweg erscheint mir das Entwerfen von URIs für Ressourcen sehr natürlich. Die Verwendung der einheitlichen Schnittstelle vereinfacht die Entwicklung, indem mit der Notwendigkeit aufgeräumt wird, für jeden Dienst eine Schnittstelle, einen Vertrag oder eine API erstellen zu müssen. Die Schnittstelle (wie Clients mit dem Dienst interagieren) wird von den Einschränkungen der Architektur festgelegt.

Wie gesagt, ist dies weder eine vollständige Liste noch sollten Sie sie als entscheidenden Beweis dafür werten, dass REST die einzig wahre Technologie ist, die immer verwendet werden sollte. Sie sollten sich der Vorteile bewusst sein, damit Sie sie ggf. nutzen können.

WCF und REST

WCF ist das Microsoft-Framework zum Erstellen von Anwendungen, die unabhängig von Stil oder Protokoll über ein Netzwerk kommunizieren. Das Konzept hinter WCF bestand darin, ein erweiterbares und austauschbares Framework zu erstellen, damit Entwickler ein Programmier- und Konfigurationsmodell kennenlernen und diese Fähigkeiten dann auf viele verschiedene Arten von verteilten Systemen anwenden können.

Es trifft zwar zu, dass Vieles in WCF auf RPC ausgerichtet ist (unter Verwendung von SOAP), aber in Wirklichkeit können mit WCF REST-Dienste verfügbar gemacht und genutzt werden, da es anfänglich als Bestandteil von .NET Framework 3.0 veröffentlicht wurde. Was ihm fehlte, war ein Programmiermodell, das erforderlich ist, um die Verwendung von REST mit WCF einfach zu gestalten. Außerdem mussten einige Bestandteile der Infrastruktur erstellt werden, damit REST mit .NET Framework 3.0 zusammenarbeitet. Sowohl ein Programmiermodell als auch diese Bestandteile der Infrastruktur wurden WCF in .NET Framework 3.5 in der System.ServiceModel.Web-Assembly hinzugefügt. Mit .NET Framework 3.5 SP1 wurden ebenfalls einige kleine Verbesserungen hinzugefügt.

Das Programmiermodell baut auf zwei neuen Attributen auf, WebGetAttribute und WebInvokeAttribute, sowie einer URI-Vorlagenmethode, mit der Sie den URI und das Verb deklarieren können, auf die jede Methode reagiert. Die Infrastruktur wird in Form einer Bindung (WebHttpBinding) und eines Verhaltens (WebHttpBehavior) bereitgestellt, mit denen der richtige Netzwerkstapel für die Verwendung von REST bereitgestellt wird. Außerdem gibt es von einem benutzerdefinierten ServiceHost (WebServiceHost) und einer ServiceHostFactory (WebServiceHostFactory) Hilfe für die Hostinfrastruktur.

WebGetAttribute und WebInvokeAttribute

Eine der Arten, auf die WCF das Erstellen verteilter Systeme vereinfacht, ist das Weiterleiten von Netzwerknachrichten an Methoden in Instanzen der Klassen, die Sie als Implementierungen Ihres Diensts definieren. Dadurch können Sie sich auf die Logik des Codes in Ihren Diensten konzentrieren und müssen sich nicht um die erforderliche Infrastruktur zum Verarbeiten des Netzwerkverkehrs kümmern.

Standardmäßig führt WCF dieses Routing (auch „Verteilen“ genannt) auf Grundlage des Konzepts der Aktion durch. Damit dieses Verteilen funktioniert, muss in jeder Nachricht, die WCF in Ihrem Auftrag empfängt, eine Aktion vorhanden sein. Jede eindeutige Aktion ist einer bestimmten Action-Methode zugeordnet.

Der Wert von Action basiert entweder auf dem Namen Ihrer Methode (plus dem Namespace Ihres Diensts) oder einem benutzerdefinierten Wert (festgelegt über die OperationContractAttribute.Action-Eigenschaft). Dieses Routingsystem ist eng an SOAP gekoppelt, da standardmäßig der Action-Header der SOAP-Spezifikation verwendet wird. Glücklicherweise ist die standardmäßige Verteilungsinfrastruktur ersetzbar, wie fast alles in WCF.

Wenn Sie die REST-Infrastruktur mit WCF verwenden, wird der Standardverteiler durch einen ersetzt, mit dem nicht auf Grundlage von Action weitergeleitet wird, sondern basierend auf dem URI der eingehenden Anforderung und des verwendeten HTTP-Verbs. Mithilfe dieses Routing (durchgeführt von einer Klasse namens „WebHttpDispatchOperationSelector“) können Sie problemlos einen REST-Endpunkt implementieren. Dieser Verteiler wird an jedem Endpunkt durch ein Verhalten namens „WebHttpBehavior“ konfiguriert, das jedem Endpunkt hinzugefügt werden muss, von dem dieses Programmiermodell verwendet werden soll. Dies müssen Sie jedoch nicht oft manuell erledigen, wie Sie später sehen werden.

Damit dies funktioniert, ist es entscheidend, dass der WebHttpDispatchOperationSelector weiß, wie verschiedene URIs und Verben Ihren Methoden zugeordnet werden. Dazu müssen WebGetAttribute und WebInvokeAttribute den Methoden in Ihrem WCF-ServiceContract-Typ hinzugefügt werden.

Mit WebGetAttribute wird dem Verteiler mitgeteilt, dass die Methode auf HTTP GET-Anforderungen reagieren sollte. WebInvokeAttribute ist standardmäßig HTTP POST zugeordnet, aber die Eigenschaft „WebInvokeAttribute.Method“ kann darauf eingestellt werden, alle anderen HTTP-Verben zu unterstützen, wobei PUT und DELETE die beiden gängigsten sind. Der URI wird standardmäßig anhand des Namens der Methode bestimmt, der dem Basis-URI des Endpunkts hinzugefügt wird.

Das sieht nicht sehr nach REST aus, da Sie sich in REST nicht mit Methodennamen befassen möchten, weil sie Verben repräsentieren. Was Sie als URIs verfügbar machen möchten, sind Nomen. Aus diesem Grund ermöglicht das WCF-REST-Programmiermodell die Anpassung von URIs für jede Methode mithilfe von Vorlagen, die über die UriTemplate-Eigenschaft für WebGetAttribute oder WebInvokeAttribute festgelegt werden können.

UriTemplate und UriTemplateTable

Um die Anpassung des URI für jede Kombination von Methode und Verb zu ermöglichen, hat WCF die Möglichkeit hinzugefügt, den URI für jede Ressource mithilfe einer besonderen Vorlagensyntax zu definieren, wie z. B. jener, die weiter oben in diesem Artikel zum Beschreiben des Dienstendpunkts des MSDN Magazins verwendet wurde. Mit dieser Syntax können Sie mithilfe ersetzbarer Token die URI-Struktur definieren, die die einzelnen Methoden in Verbindung mit dem HTTP-Verb repräsentieren soll (über WebGetAttribute oder WebInvokeAttribute). Die Syntax wird in einem zukünftigen Artikel ausführlicher erklärt.

In Abbildung 2 wird die WCF ServiceContract-Definition für den MSDN Magazin-Dienst mit den geeigneten Attributen und Anpassungen in UriTemplate angezeigt. Außerdem werden die zuvor erwähnten Features angewendet. Das vorhandene WCF-Vertragsdefinitionssystem wird mit WebGetAttribute für jene Vorgänge erweitert, die auf GET reagieren sollen. Außerdem wird WebInvokeAttribute dem Vorgang hinzugefügt, um auf andere Verben zu reagieren.

Abbildung 2 WCF-ServiceContract-Definition

[ServiceContract]
public interface IMSDNMagazineService
{
    [OperationContract]
    [WebGet(UriTemplate="/")]
    IssuesCollection GetAllIssues();
    [OperationContract]
    [WebGet(UriTemplate = "/{year}")]
    IssuesData GetIssuesByYear(string year);
    [OperationContract]
    [WebGet(UriTemplate = "/{year}/{issue}")]
    Articles GetIssue(string year, string issue);
    [OperationContract]
    [WebGet(UriTemplate = "/{year}/{issue}/{article}")]
    Article GetArticle(string year, string issue, string article);
    [OperationContract]
    [WebInvoke(UriTemplate = "/{year}/{issue}",Method="POST")]
    Article AddArticle(string year, string issue, Article article);

}

In diesem Fall wurde der AddArticle-Methode „Method="POST"“ hinzugefügt, um die Lesbarkeit zu verbessern, da das Standardverb für WebInvokeAttribute POST ist. Sowohl die Methode GET als auch POST besitzen URI-Anpassung mithilfe des UriTemplate-Attributs. Die Syntax von UriTemplate lässt mehrere veränderliche Pfadsegmente zu. Jedes dieser Pfadsegmente wird als Argument an die Methoden übergeben.

WebHttpBinding und WebHttpBehavior

In WCF wird mithilfe einer Bindung bestimmt, wie WCF kommuniziert. Eine Bindung ist in Wirklichkeit die Konfiguration, mit der WCF mitgeteilt wird, wie der Kanalstapel erstellt wird. Das ist eine Reihe von Objekten, die zusammenarbeiten, um die Art von Kommunikation bereitzustellen, die für einen bestimmten Endpunkt gewünscht ist.

Für einen REST-Endpunkt wird die Bindung „WebHttpBinding“ verwendet. Im Unterschied zu vielen anderen Bindungen ist WebHttpBinding ziemlich einfach, da es nur zwei Komponenten enthält: den HTTP-Transport und den Textnachrichtencodierer (der darauf eingestellt ist, kein SOAP zu erwarten oder zu verwenden, sondern nur einfaches XML).

Wie bereits erwähnt ist WebHttpBehavior das Objekt, das die Verwendung des URI-plus-Verb-Verteilers bewirkt. Aus diesem Grund werden WebHttpBinding und WebHttpBehavior fast immer zusammen verwendet. Es folgt der Code zum Erstellen eines solchen Endpunkts, wenn Sie einen WCF-REST-Endpunkt mit Self-Hosting bereitstellen:

ServiceHost sh = 
  new ServiceHost(typeof(MSDNMagazineServiceType));
string baseUri = "http://localhost/MagazineService";
ServiceEndpoint se = 
  sh.AddServiceEndpoint(typeof(IMSDNMagazineService),
  new WebHttpBinding(), baseUri);
se.Behaviors.Add(new WebHttpBehavior());
sh.Open();

Wenn der Endpunkt zu ServiceHost hinzugefügt wird, muss nicht nur WebHttpBinding angegeben werden. Des Weiteren muss dem Endpunkt auch ausdrücklich WebHttpBehavior hinzugefügt werden, damit das URI-plus-Verb-Verteilersystem funktioniert. Selbstverständlich kann dies ebenfalls über die Konfiguration erledigt werden (siehe Abbildung 3).

Abbildung 3 URI-Plus-Verb-Verteilung in Konfiguration

<configuration>
  <system.serviceModel>
    <services>
      <service name="MSDNMagazine.MSDNMagazineServiceType">
        <endpoint 
          address="http://localhost/MagazineService" 
          binding="webHttpBinding" 
          contract="MSDNMagazine.IMSDNMagazineService" 
          behaviorConfiguration="webby"/>
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="webby">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

WebServiceHost und WebServiceHostFactory

Eine der Beanstandungen in Bezug auf WCF besteht darin, dass es manchmal zu komplex ist, besonders hinsichtlich der Konfiguration. Um dieses Problem bei REST-Endpunkten zu beheben (Einfachheit ist wiederum einer der häufig genannten Vorteile von REST), hat Microsoft zu .NET Framework 3.5 zwei neue Typen hinzugefügt, WebServiceHost und WebServiceHostFactory.

WebServiceHost ist ein von ServiceHost abgeleiteter Typ, der Self-Hosting-Szenarios von REST-Endpunkten vereinfacht. Der Code zum Hosten mit WebServiceHost sieht folgendermaßen aus:

string baseUri = "http://localhost/MagazineService";
WebServiceHost sh = 
  new WebServiceHost(typeof(MSDNMagazineServiceType),
  new Uri(baseUri));
sh.Open();

Dies ist eine gute Optimierung, weil dadurch der sich wiederholende Code durch das manuelle Hinzufügen von WebHttpBinding und WebHttpBehavior vermieden wird. Mit der WebServiceHost-Klasse wird der Endpunkt automatisch erstellt und mit WebHttpBinding und WebHttpBehavior konfiguriert.

Im Szenario mit verwaltetem Hosting mittels WCF innerhalb von IIS (Internet Information Services) erfordert WCF normalerweise eine .svc-Datei, die auf den Diensttyp zeigt, sowie Einträge in die web.config-Datei, um WCF über den Endpunkt zu informieren (die Bindung und die Verhaltensweisen nebst weiterer Konfiguration).

Um das Szenario mit verwaltetem Hosting zu vereinfachen, hat Microsoft WebServiceHostFactory hinzugefügt. Dies erstellt mit einem offenen WCF-Erweiterungspunkt und mithilfe eines benutzerdefinierten ServiceHostFactory-Typs im Szenario mit verwaltetem Hosting eine konfigurationsfreie Funktionalität für viele REST-Dienste. Die .svc-Datei sieht wie folgt aus:

<%@ ServiceHost Factory=
  "System.ServiceModel.Activation.WebServiceHostFactory"   
  Service="MSDNMagazine.MSDNMagazineServiceType" %>

Mit WebServiceHostFactory wird eine Instanz von WebServiceHost erstellt. Da WebServiceHost den Endpunkt mithilfe von WebHttpBinding und WebHttpBehavior automatisch konfiguriert, muss in web.config keine Konfiguration für diesen Endpunkt vorhanden sein. (Wenn Sie die Bindung anpassen müssen, müssen Sie selbstverständlich das Konfigurationssystem verwenden oder eine Klasse erstellen, die von WebServiceHost/WebServiceFactory abgeleitet wird.) Wenn die Bindung angepasst werden musste, können der Konfigurationsdatei immer noch entsprechende Einträge hinzugefügt werden. In Abbildung 4 wird eine Konfigurationsdatei gezeigt, durch die am Dienstendpunkt HTTP-Standardauthentifizierung aktiviert würde.

Abbildung 4 Aktivieren der HTTP-Standardauthentifizierung

<configuration>
<system.serviceModel>
  <services>
    <service name="MSDNMagazine.MSDNMagazineServiceType">
      <endpoint 
        address="http://localhost/MagazineService" 
        binding="webHttpBinding" 
        contract="MSDNMagazine.IMSDNMagazineService" 
        behaviorConfiguration="webby"/>
    </service>
  </services>
  <bindings>
    <webHttpBinding>
      <binding name="secure">
        <security mode="Transport">
          <transport clientCredentialType="Basic"/>
        </security>
      </binding>
    </webHttpBinding>
  </bindings>
  <behaviors>
    <endpointBehaviors>
      <behavior name="webby">
        <webHttp/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>
</configuration>

Verwenden des Beispielcodes

Durch die Erklärung der Features von WCF in Bezug auf REST wurde der Großteil der Implementierung des Diensts angelegt, der zu Beginn des Artikels vorgeschlagen wurde. Jetzt werde ich Sie schrittweise durch die Interaktion mit diesem Dienst leiten.

Sobald der Dienst fertiggestellt ist und ausgeführt wird, kann dessen Stamm-URI mit einem beliebigen Client aufgerufen werden, einschließlich eines Webbrowsers wie Internet Explorer. Die Fähigkeit, mit einem Browser schnelle Tests an REST-Endpunkten auszuführen, ist eine recht nützliche Folge davon, dass der REST-Architekturstil auf der Art und Weise basiert, wie das Internet funktioniert. Das Ergebnis ist in Abbildung 5 dargestellt.

fig05.gif

Abbildung 5 Stammressourcen-URI

In diesem Fall wird im Visual Studio 2008 Web Development Server gehostet, der den Standard-URI vorgibt. Die Datei „Issues.svc“ ist die erforderliche Datei für WCF im Szenario mit verwaltetem Hosting. Wenn das Ergebnis für ein bestimmtes Jahr angezeigt werden soll, muss lediglich dieses Jahr der Adresse (dem URI) im Browser hinzugefügt werden (siehe Abbildung 6).

fig06.gif

Abbildung 6 Die Ressource, die das Jahr 2007 repräsentiert

Wenn nach Oktober 2008 gefragt wird, würde der URI „localhost:1355/Issues.svc/2008/October“ lauten, der zu diesem Zeitpunkt ein leerer Satz wäre. Wenn ein Artikel hinzugefügt werden soll, wird ein HTTP POST für diesen URI durchgeführt, mit der XML-Darstellung eines Artikels als HTTP-Anforderungstext.

Ein weiteres nützliches Feature von HTTP sind all die Tools, die für die Interaktion zur Verfügung stehen. Einer meiner Favoriten ist Fiddler, mit dem HTTP-Anforderungen und -Antworten „ausspioniert“ werden können. Aber es gibt auch ein Feature, mit dem beliebige HTTP-Vorgänge durchgeführt werden können. Mithilfe der Registerkarte „Fiddler Request Builder“ kann HTTP POST durchgeführt werden (siehe Abbildung 7). Nach dem POST in Abbildung 8 können Sie eine Anforderung für die Ressource von Oktober 2008 sehen.

fig07.gif

Abbildung 7 Durchführen einer HTTP POST-Anforderung zum Erstellen einer neuen Artikelressource mittels Fiddler

fig08.gif

Abbildung 8 Artikelressource hinzugefügt

Obwohl argumentiert werden kann, dass Internet Explorer und Fiddler echte Clients sind, ist das Erstellen einer tatsächlichen Client-Server-Implementierung eine Erweiterung der oben genannten einfachen Schritte. (In einem späteren Artikel wird ein komplexeres Beispiel für das Erstellen eines REST-Clients behandelt.) Ein Client muss den URI jeder Ressource kennen und wissen, welche Bestandteile der einheitlichen Schnittstelle für jeden URI verwendet werden sollen. Der Client kann dann mithilfe dieser Informationen mit dem Dienst interagieren, um seine Funktionalität auszubauen.

In diesem ersten Artikel wurde der Basissatz von WCF-Features gezeigt, mit denen der REST-Architekturstil problemlos in Ihren .NET-Anwendungen verwendet werden kann. Diese Grundlage ermöglicht weitere interessante Technologien, einschließlich Webfeeds (RSS und Atom) und Unterstützung von mit JSON kodierten Ressourcen für die Interaktion mit AJAX.

In den nächsten Artikeln wird auf diesem grundlegenden Wissen bezüglich REST und WCF aufgebaut und auf die Details mehrerer weiterer Features in der Microsoft-Plattform eingegangen, die auf diesem Stil und dieser Technologie aufbauen. Außerdem werden einige der häufigen Fragen zu REST beantwortet, zum Beispiel in Bezug auf die Sicherheit sowie zur Implementierung von Verarbeitungsendpunkten.

Senden Sie Fragen und Kommentare in englischer Sprache an sstation@microsoft.com.

Jon Flanders ist unabhängiger Berater, Referent und Trainer für Pluralsight. Seine Spezialgebiete sind BizTalk Server, Windows Workflow Foundation und Windows Communication Foundation. Sie erreichen Jon Flanders unter masteringbiztalk.com/blogs/jon.