© Martin Korneffel,
Stuttgart 2004 +++ email: trac@n.zgs.de
+++ web: www.s-line.de/homepages/trac
Webservice + WCF
Inhalt
Was
ist ein Webservice
Vorteile
von Webservices
ASMX-
Webservices
WCF
Einen
Webservice nutzen
Varianten
zum Abruf eines ASMX- Webservices
Technische
Grundlagen
Client/Server
Web-,
Service Referenzen und Proxyklassen
HTTP
SOAP
WSDL
WebServices
erstellen
ASMX
WebService- Klassen
Lebenszyklus
eines ASMX Webservice- Objektes
Implementieren
einer ASMX- WebService- Klasse
Attribute
für WebService- Klassen
Attribute
für WebService- Methoden
Behandlung
von Ausnahmen
Komplexe
Parameter und Rückgabewerte
Strukturen
und Klassen
Arrays
und Listen
Webservices
mit "Gedächnis"
Konsumieren
von Webservices
Suchen
von Webdiensten
Dienstveröffentlichungen
mittels UDDI und DISCO
Erstellen
von Proxyklassen
Asynchroner
Aufruf von Webservices
Rückgabewert
IAsyncResult
Schützen
eines Webservices
Variante
1: Login- Daten über SoapHeader senden
Aufruf
des gesicherten Dienstes über die Proxyklasse
Variante
2 : Anmelden mit neuer Identität unter Windows
Konfiguration
des Webservices
Debugging
aktivieren
Tracing
aktivieren
Definieren
der Zugriffsmethoden
WSE
3.0
Installation
von X509 Zertifikaten
Zertifikatstool
Konfigurationstool
Konfiguration
von Dienst und Client
Integration
von WSE
Spezielle
Basisklasse der Proxys auf der Clientseite
Installation
einer spezialisierten Classfactory für Soap- Protokolle auf
der Serviceseite
Effiziente
Übertragung großer Datenblöcke mittels MTOM
Windows
Dienst als Webservice Host
Sichern
von Webdiensten durch Verschlüsseln von Soap Nachrichten
Probleme
mit WSE 3.0
WCF-Service
Endpunkte
Bindungen
Was ist ein
Webservice
Definition
|
Webservice
|
Ein Webservice ist ein Dienst im Netz, der
standardisierten, herstellerunabhängige, formale Sprachen
einsetzt um:
abrufbaren Methoden aufzulisten (z.B.
WSDL)
die Datenstrukturen der Parameter und
Rückgabewerte zu definieren (z.B. WSDL)
Methodenaufruf abzubilden (z.B. SOAP)
die Ergebnisse darzustellen (z.B. SOAP)
|

Vorteile
von Webservices
Webservices können plattformübergreifend
genutzt werden
Webservices können auch über
Firewallgrenzen hinweg aufgerufen werden. Die Kommunikation mit
Webservices erfolgt analog dem Aufruf von Webseiten. Es ist nur ein
TCP- Port notwendig (z.B. 80) -> Firewalls können überwunden
werden
Zur Webdiensttechnologie gehören
Registrierungen wie UDDI und DISCO. Dadurch sind Webdienste ähnlich
Webseiten auffindbar und katalogisierbar
ASMX- Webservices
Das ASP.NET Framework ermöglicht die
Implementierung von Webservices auf IIS. Kern der Implementierung
sind dabei Instanzen der Webservice- Klasse, die SOAP- und WSDL
Requests über HTTP verarbeiten.
Mittels der WSE (Webservice Enhancements)
Bibliothek wurden ASMX Webservices um Techniken zur effizienteren
Übertragung von Binärdaten und Verschlüsselte
Datenübertragung aufgerüstet.
WCF
Seit .NET 3.0 gibt es die Windows Communication
Foundation Bibliothek. Mit ihr
können Webservices unabhängig von ASP.NET und IIS
implementiert werden. Zudem integriert sie Techniken aus der WSE. WCF
verallgemeinert die Webservices zu einer Service- orientierten
Technologie (SOA).
Einen Webservice
nutzen

Varianten
zum Abruf eines ASMX- Webservices
ASMX- Webservices sind mit allen Formen von HTTP-
Requests abrufbar. So können die Aufrufparameter in einem
Request als SOAP- Telegramme, Qeurystrings oder Formulardaten
gesendet werden.

Achtung:
Die Methoden Get und Post unterstützen keine komplexen
Datentypen. Dafür ist ihr Einsatz resourcenschonender in kleinen
Diensten gegenüber SOAP.
Technische Grundlagen
Im folgenden werden Grundbegriffe für das
Verständnis von ASMX und WCF- Webdienste erläutert
Client/Server
Webdienste werden von Clients konsumiert. Ein
Client kann ein z.B. ein Webbrowser, ein Kommandozeilenprogramm oder
eine weitere Serveranwendung sein.
Web-,
Service Referenzen und Proxyklassen
Die mit WSDL gelieferten Metadaten sind maschinell
auswertbare XML Dateien, die den Webservice vollständig
beschreiben. Entwicklungswerkzeuge wie Visual- Studio können aus
diesen sog. Proxyklassen generieren, welche den Dienstaufruf
über HTTP, und die Serialisierung/Deserialisierung der
Parameter/Ergebnisse in Eigenschaften und Methoden kapseln.

Innerhalb
eines Visual- Studio Projektes werden die Proxyklassen für ASMX-
Webdienste unter Webservice- Referenzen, und für WCF-
Dienste unter Service- Referenzen verwaltet.
HTTP
Definition
|
URL
|
Ein URL (engl.: Uniform Resource Locator)
bezeichnet eine Resource im Internet und enthält explizit
Anweisungen, wie auf diese Resource zugegriffen werden kann.
Allgemeiner Aufbau:
http://host[:port][path[?querystring]]
|
SOAP
Simple Object Access Protrocol
Allgemeiner Aufbau eines SOAP- Nachricht

Beispiel:
Aufruf und Resultat von DMSsearch als SOAP- Nachrichten
POST /asp-mcsd2/DMSsearch/dmssearch.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://www.tracs.de/search"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<search xmlns="http://www.tracs.de">
<stichwort>string</stichwort>
</search>
</soap:Body>
</soap:Envelope>
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<searchResponse xmlns="http://www.tracs.de">
<searchResult>
<xsd:schema>schema</xsd:schema>xml</searchResult>
</searchResponse>
</soap:Body>
</soap:Envelope>
WSDL
Meta und Typinformationen über Webservices
werden in einer standardisierten Sprache verfasst, genannt Webservice
Description Language oder kurz WSDL. WSDL- Beschreibungen sind
XML- Dateien, welches das XML- Schema- Vokabular einsetzt. ASP.NET
erzeugt für einen Webservice diese Beschreibungen automatisch.
Sie können über einen Uri mit dem Querystring WSDL
zu jedem Dienst über das Web abgerufen werden:
http://localhost:1516/BlogWebSvr/BlogWebService.asmx?WSDL
Das
Ergebnis ist z.B. eine WSDL- Datei wie folgende:
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://www.tracs.de/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://www.tracs.de/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="http://www.tracs.de/">
<s:element name="HelloWorld">
<s:complexType />
</s:element>
<s:element name="HelloWorldResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="HelloWorldResult" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="blog">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="Autor" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="Message" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="blogResponse">
<s:complexType />
</s:element>
<s:element name="GetAllBlogs">
<s:complexType />
</s:element>
<s:element name="GetAllBlogsResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="GetAllBlogsResult" type="tns:ArrayOfBlogEntry" />
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="ArrayOfBlogEntry">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="BlogEntry" nillable="true" type="tns:BlogEntry" />
</s:sequence>
</s:complexType>
<s:complexType name="BlogEntry">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="Timestamp" type="s:dateTime" />
<s:element minOccurs="1" maxOccurs="1" name="MsgId" type="s:int" />
<s:element minOccurs="0" maxOccurs="1" name="Message" type="s:string" />
</s:sequence>
</s:complexType>
</s:schema>
</wsdl:types>
<wsdl:message name="HelloWorldSoapIn">
<wsdl:part name="parameters" element="tns:HelloWorld" />
</wsdl:message>
<wsdl:message name="HelloWorldSoapOut">
<wsdl:part name="parameters" element="tns:HelloWorldResponse" />
</wsdl:message>
<wsdl:message name="blogSoapIn">
<wsdl:part name="parameters" element="tns:blog" />
</wsdl:message>
<wsdl:message name="blogSoapOut">
<wsdl:part name="parameters" element="tns:blogResponse" />
</wsdl:message>
<wsdl:message name="GetAllBlogsSoapIn">
<wsdl:part name="parameters" element="tns:GetAllBlogs" />
</wsdl:message>
<wsdl:message name="GetAllBlogsSoapOut">
<wsdl:part name="parameters" element="tns:GetAllBlogsResponse" />
</wsdl:message>
<wsdl:portType name="BlogWebServiceSoap">
<wsdl:operation name="HelloWorld">
<wsdl:input message="tns:HelloWorldSoapIn" />
<wsdl:output message="tns:HelloWorldSoapOut" />
</wsdl:operation>
<wsdl:operation name="blog">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Blog</wsdl:documentation>
<wsdl:input message="tns:blogSoapIn" />
<wsdl:output message="tns:blogSoapOut" />
</wsdl:operation>
<wsdl:operation name="GetAllBlogs">
<wsdl:input message="tns:GetAllBlogsSoapIn" />
<wsdl:output message="tns:GetAllBlogsSoapOut" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="BlogWebServiceSoap" type="tns:BlogWebServiceSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="HelloWorld">
<soap:operation soapAction="http://www.tracs.de/HelloWorld" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="blog">
<soap:operation soapAction="http://www.tracs.de/blog" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetAllBlogs">
<soap:operation soapAction="http://www.tracs.de/GetAllBlogs" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="BlogWebServiceSoap12" type="tns:BlogWebServiceSoap">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="HelloWorld">
<soap12:operation soapAction="http://www.tracs.de/HelloWorld" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="blog">
<soap12:operation soapAction="http://www.tracs.de/blog" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetAllBlogs">
<soap12:operation soapAction="http://www.tracs.de/GetAllBlogs" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="BlogWebService">
<wsdl:port name="BlogWebServiceSoap" binding="tns:BlogWebServiceSoap">
<soap:address location="http://localhost:1516/BlogWebSvr/BlogWebService.asmx" />
</wsdl:port>
<wsdl:port name="BlogWebServiceSoap12" binding="tns:BlogWebServiceSoap12">
<soap12:address location="http://localhost:1516/BlogWebSvr/BlogWebService.asmx" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
WebServices erstellen
Wir schreiben das Jahr 2009, und es gibt
mittlerweile mehrere Möglichkeiten unter .NET, Webservices zu
implementieren.
In den Versionen bis einschließlich .NET 2.0
stützen sich Webservices voll auf ASP.NET und IIS. Ab 3.0 sind
mit der WCF- Bibliothek auch Webservices außerhalb von ASP.NET
und IIS implementierbar. So kann auch ein Kommandozeilenprogramm
befähigt werden, Webservices anzubieten.
ASMX WebService-
Klassen
Webdienste werden durch Klassen implementiert, die
von der Klasse WebService abgeleitet sind:

Lebenszyklus
eines ASMX Webservice- Objektes

Implementieren
einer ASMX- WebService- Klasse
Für den
praktischen Einsatz benötigt ASP.NET noch weitere Informationen
zum Dienst, wie der Name, der zu verwendende Namespace und eine
Kurzbeschreibung. Diese werden den Metadaten der Klasse durch das
Attribut WebService hinzugefügt:
[WebService(Namespace="http://www.tracs.de",
Name="DMSSearch",
Description="Suche von Dokumenten bezüglich Stichworte")]
public class DMSSearch : System.Web.Services.WebService {
[WebMethod] public DataSet search(string stichwort)
{
DataSet ds = new DataSet();
:
return ds;
}
}
Attribute
für WebService- Klassen

Beispiel:
[WebService(Namespace = "http://www.tracs.de/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class BlogWebService : System.Web.Services.WebService
{
//...
}
Attribute für WebService- Methoden

Beispiel:
const string IdInstanzCounter = "InstanzCounter";
[WebMethod(Description = "Testet WebMethod Attribute",
MessageName = "WebMethodenAttributTest",
EnableSession = true)]
public int TestWebMethod()
{
if (Session[IdInstanzCounter] == null)
Session[IdInstanzCounter] = 0;
else
Session[IdInstanzCounter] = (int)Session[IdInstanzCounter] + 1;
return (int)Session[IdInstanzCounter];
}
Testumgebung für die Webmethode:
// CookieContainer zum Aufbewahren der "Kekse" für Sessions
System.Net.CookieContainer cookieContainer = new System.Net.CookieContainer();
private void btnTestWebMethodAttribute_Click(object sender, EventArgs e)
{
localhost.TestWebSvr webSvr = new global::TestWebservices.localhost.TestWebSvr();
// Zuweisen des CookieContainers zur Aufbewahrung der Cookies, über die
// Sitzungen identifiziert werden
webSvr.CookieContainer = cookieContainer;
log.LogMsg(0, "TestWebMethodAttribute: InstanzCount=" + webSvr.TestWebMethod().ToString());
}
Behandlung von
Ausnahmen
Beim werfen von Ausnahmen muß beachtet
werden, daß diese serialisierbare Objekte darstellen. Im
Framework wird hierfür die ideale Klasse
System.Web.Services.Protocols.SoapException angeboten.

Beispiel:
Wegmehtode, die
Ausnahmen auslöst
[WebService(Namespace = "http://www.tracs.de/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class TestWebSvr : System.Web.Services.WebService
{
public TestWebSvr()
{
//Auskommentierung der folgenden Zeile bei Verwendung von Designkomponenten aufheben
//InitializeComponent();
}
public enum ExceptionTypes
{
standard,
soap,
Null
}
[WebMethod(Description = "Testen von Ausnahmen")]
public void TesteAusnahme(ExceptionTypes type)
{
switch(type) {
case ExceptionTypes.standard:
throw new Exception("Eine Standardausnahme");
break;
case ExceptionTypes.soap:
throw new SoapException("Eine Soap Exception", SoapException.ClientFaultCode, Context.Request.Url.AbsoluteUri);
break;
default:
throw new SoapException("Eine Serverfehler Soap Exeption", SoapException.ServerFaultCode, "ich");
}
}
}
Zugriff auf einen Webservice aus einer Applikation und Anfangen der
Ausnahmen
private void btnTesteAusnahmen_Click(object sender, EventArgs e)
{
localhost.TestWebSvr webSvr = new global::TestWebservices.localhost.TestWebSvr();
try
{
webSvr.TesteAusnahme(global::TestWebservices.localhost.ExceptionTypes.standard);
}
catch (Exception ex)
{
log.LogMsg(0, "Standardausnahme: " + ex.Message);
}
try
{
webSvr.TesteAusnahme(global::TestWebservices.localhost.ExceptionTypes.soap);
}
catch (System.Web.Services.Protocols.SoapException ex)
{
log.LogMsg(0, "Soapausnahme: " + ex.Message + " Actor=" + ex.Actor.ToString() + " Code=" + ex.Code.ToString());
}
}
Komplexe Parameter und Rückgabewerte
Die übergabe von Werten fundamentaler
Datentypen wie int und string ist problemlos möglich.
Bei komplexen Datentypen können zusätzliche Schritte
notwendig sein.
Strukturen
und Klassen
Die bei der Deserialisierung Komplexer Datentypen
werden diese mittels Defaultkonstruktor instanziiert werden.
Datenstrukturen haben immer einen Defaultkonstruktor. Bei Klassen muß
ein Defaultkonstruktor explizit angegeben werden, falls die Klasse
vom Defaultkonstruktor verschiedene Konstruktoren besitzt.
Webservices ermöglichen kein Remoting.
Folglich müssen alle Typen als MBV Werte übergeben werden
(Serializable).
[Serializable]
public struct Point
{
public double x;
public double y;
}
[Serializable]
public class Shape {
public int id;
}
[Serializable]
public class Line : Shape
{
public Line()
{
}
public Line(Point a, Point b)
{
this.a.x = a.x;
this.a.y = a.y;
this.b.x = b.x;
this.b.y = b.y;
}
public Point a = new Point();
public Point b = new Point();
}
Arrays und Listen
Arrays und Listen können problemlos übergeben
und zurückgegeben werden, solange sie homogen sind. Homogen ist
ein Array oder eine Liste, wenn ihre Elemente alle den gleichen Typ
haben. Im folgenden Beispiel werden alle Blogs aus dem Blogserver
ausgelesen und über eine Webmethode als Liste an einem Clienten
übergeben:
[WebMethod]
public System.Collections.Generic.List<DMS.BlogServer.BlogEntry> GetAllBlogs()
{
try
{
DMS.BlogServer blogServer = new DMS.BlogServer();
return blogServer.GetAllBlogs();
}
catch (Exception ex)
{
throw new SoapException(ex.Message, SoapException.ServerFaultCode);
}
}
Zugriff auf die Webmethode über dem Clienten
private void btnGetBlogs_Click(object sender, EventArgs e)
{
try
{
BlogServer.BlogWebService webSvr = new global::TestWebservices.BlogServer.BlogWebService();
dataGridView1.DataSource = webSvr.GetAllBlogs();
}
catch (System.Web.Services.Protocols.SoapException ex)
{
log.LogMsg(0, "GetBlogs: " + ex.Message);
}
}
Werden jedoch heterogene Arrays zurückgegeben, dann ist ein
zusätzlicher Schritt erforderlich. In diesem Fall muß der
Deserialisierer über die möglichen Kandidaten im Array
informiert werden. Ohne diese Informationen wird bei der
Deserialisierung eine Exception geworfen. Im folgenden Beispiel
erzeugt die Webmethode GetDrawing eine Liste aus Linien und
Kreisobjekten, und gibt diese zurück.
[WebMethod]
[XmlInclude(typeof(Line))]
[XmlInclude(typeof(Circle))]
public List<Shape> GetDrawing()
{
List<Shape> dw = new List<Shape>();
dw.Add(new Circle(new Point(0, 0), 10));
dw.Add(new Line(new Point(0, 0), new Point(10, 10)));
return dw;
}
Webservices mit "Gedächnis"
Die Statusverwaltung aus ASP.NET ist ebenfalls für
Webservices gültig (siehe: Prozesse
in einer ASP.NET Anwendung).
Allerdings muß die Aufbewahrung der Cookies
auf der Clientseite in die eigene Hand genommen werden, da der kein
Browswer sondern ein selbstprogrammiertes etwas ist. Dazu werden die
Cookies in einem Objekt vom Typ System.Net.CookieContainer im
Client zwischengespeichert. Vor jedem Aufruf ist der Eigenschaft
CookieContainer der Proxyklasse der CookieContainer
zuzuweisen:

Bsp:
Status 2- Durch Applikations- und Sitzungsvariablen implementierte
Zähler.
Konsumieren
von Webservices
Suchen von
Webdiensten
Definition
|
discovery
|
Unter discovery wird der Prozess des
Erkundens von Webdiensten in einem Netz verstanden
|
Dienstveröffentlichungen mittels UDDI und DISCO
Um Dienste zu nutzen, muß man wissen, wo Sie
angeboten werden, und wie sie aufzurufen sind. Unterstützung
findet man dabei durch UDDI- Server (Universal Description ,
Discovery and Integration) bzw. DISCO- Link- Dateien.
UDDI- Server
siehe. VS- Studio
Disco- Datei mit Verweisen auf Dienste
<?xml version="1.0" encoding="utf-8" ?>
<discovery xmlns="http://schemas.xmlsoap.org/disco/"
xmlns:disco="http://schemas.xmlsoap.org/disco/scl/">
<disco:discoveryRef ref="http://localhost/asp-mcsd2/DMSsearch/dmssearch.asmx?DISCO"/>
<disco:discoveryRef ref="http://localhost/myServices/add/add.asmx?DISCO"/>
</discovery>
Proxyklassen

Struktur
der Basisklasse

Erstellen
von Proxyklassen
In Visual Studio wird die Erstellung von
Proxyklassen voll automatisiert durch die Webverweise. Grundlage
dafür sind die WSDL- Beschreibungen, die ASP.NET für jeden
Webservice automatisch generiert. Eine WSDL- Beschreibung kann stets
über den Querystring ?WSDL zu einem Webservice abgerufen
werden.
http://localhost:1516/BlogWebSvr/BlogWebService.asmx?WSDL

Asynchroner
Aufruf von Webservices

Schützen
eines Webservices
Variante 1: Login- Daten über SoapHeader senden
Unabhängig von den Parameter der
Dienstmethoden können über einen SoapHeader weiter
Daten bei jedem Dienstaufruf übermittel werden. Dazu wird von
der Klasse SoapHeader ein neue Klasse abgeleitet, die den neuen
SoapHeader darstellt:
public class CLogin : System.Web.Services.Protocols.SoapHeader {
public string user;
public string password;
}
In der Webservice- Klasse muß ein Member vom Typ des neuen
SoapHeader angelgt werden:
[WebService...]
public class CSaveService : System.Web.Services.WebService {
public CLogin Login;
:
}
Die zu sichernde Dienstmethode muß mit dem SoapHeader
ausgestattet werden. Dies geschieht über das Attribut WebMethod:
[WebMethod(), SoapHeader("Login")]
public string getMe()
{
if (Login == null)
throw new Exception("Authentifizierung erforderlich");
if (Login.user == "Waldi" && Login.password=="Wurst")
return "Sie haben Zugang";
else
throw new Exception("Login ungültig");
}
Der Dienst ist damit gesichert.
Aufruf des gesicherten Dienstes über die Proxyklasse
private void btnGet_Click(object sender, System.EventArgs e)
{
try
{
localhost.SaveService serv = new testSaveService.localhost.SaveService();
localhost.CLogin login = new testSaveService.localhost.CLogin();
login.username = tbxUser.Text;
login.password = tbxPassword.Text;
serv.SLoginValue = login;
this.lblResultat.Text = serv.getMe();
}
catch (Exception ex)
{
lblResultat.Text = ex.Message;
}
}
Variante 2 : Anmelden mit neuer Identität unter Windows
Objekt von System.Net.NetworkCredential
instanziieren
NetworkCredential UserName und Passwort
zuweisen
Objekt von System.Net.CredentialCache
instanziieren. CredentialCache speichert mehrere
Anmeldeinformationen
-

Konfiguration
des Webservices
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.web>
<!-- ... -->
</system.web>
</configuration>
Debugging aktivieren
<compilation debug="true"/>
Tracing aktivieren
<trace enabled="true"/>
Definieren
der Zugriffsmethoden
Die möglichen Zugriffsmethoden wie HttpGet
oder HttpSoap werden in der web.config Datei wie folgt
definiert:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
<remove name="HttpSoap"/>
</protocols>
</webServices>
:
</system.web>
</configuration>
In diesem Fall würden nur die Zugriffsmethoden Get und Post
unterstützt.
WSE 3.0
WSE ist die Abkürzung für Web Service
Enhancements. Durch WSE wird das .NET Framework wie folgt
erweitert:
Vereinfachte
Sicherung von Webservices durch deklarative Konfiguration von
Authentifizierung, Signierung und Verschlüsselung
Effiziente
Übertragung großer binärer Datenmengen
Routing von
Webservices zwecks Wartung und Ausfallsicherung
Klassen zum
Schreiben von Stand- Alone Webservice Anwendungen, wodurch kein IIS
mehr zum Hosten von WS notwendig ist
SOAP Messaging
(Webmethoden ohne Response)
Viele Funktionen in WSE sind nach Installation von
WSE durch Konfigurationsdateien administrativ einstellbar. Damit sind
Webservices nachträglich ohne Reimplementierung um die WSE
Funktionen erweiterbar.
Installation
von X509 Zertifikaten
Um Soap- Nachrichten zu signieren und zu
verschlüsseln, müssen X509 Zertifikate auf dem Client und
dem Server installiert werden. Für die authentifizierung muß
eine Serverzertifikat angelegt werden, welches auf dem Serverrechner
unter
Localmachine\Personal
und auf dem Client unter
CurrentUser\OtherPerson
abgelegt werden muß.
Für
Testzwecke können die Zertifikate der Samples von WSE 3.0
genutzt werden. Diese werden mittels
C:\Programme\Microsoft WSE\v3.0\Samples\Setup.bat
automatisch installiert.
Zertifikatstool
WSE 3.0 liegt ein Tool zur Verwaltung von
Zertifikaten bei. Webservices benötigen auf dem Server Zugriff
auf die Datei mit dem privaten Schlüssel des Zertifikates. Die
NTFS- ACL dieser Datei kann komfortabel mit dem Tool eingestellt
werden, indem es ins Tool geladen (Open Certificate), und
anschließend mittels View Private Key Properties geöffnet
wird. Unter Sicherheit muß auf Windows XP der Benutzer ASPNET,
oder unter Server 2003 der Benutzer NETZWERKDIENST Vollzugriff haben.
Konfigurationstool
Die administrative Steuerung von WSE durch
Konfigurationsdateien wird durch ein spezielles Konfigurationstool,
dem WseConfigEditor3.exe, erleichtert. In dieses kann eine
web.config Datei eines Webservices geladen und anschließend
über eine GUI die Konfiguration der WSE- Funktionen integriert
werden.
Konfiguration
von Dienst und Client
Mit dem WseConfigEditor3.exe werden Client
und Server konfiguriert. Dazu ist über File/Open die
entsprechende Web.Config oder App.config Datei zu öffnen:

Integration von
WSE
Die zusätzlichen Funktionen von WSE werden
durch eine spezielle Basisklassen für die Proxyklasse der
Clients, und eine SoapProtocollFactory für die Webservices
bereitgestellt.
Spezielle Basisklasse der Proxys auf der Clientseite

Installation
einer spezialisierten Classfactory für Soap- Protokolle auf der
Serviceseite
Ein Webservice wird auf WSE erweitert, indem das
Element <soapServerProtocolFactory> der web.config
Datei hinzugefügt wird:
<webServices>
<soapServerProtocolFactory type="Microsoft.Web.Services3.WseProtocolFactory,
Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</soapExtensionImporterTypes>
</webServices>
Effiziente Übertragung großer Datenblöcke mittels
MTOM
MTOM steht für Message Transmission
Optimization Mechanism. Große Blöcke binärerer
Daten wie z.B. Bilddaten werden direkt in die Soapnachrichten
eingebunden. Die auf einfache Soap- Nachrichten angewendeten
Signierungs- und Verschlüsselungsalgorithmen werden damit auch
auf die Übertragung großer binärer Datenmengen
erweitert. Findet keine Signierung oder Verschlüsselung statt,
dann werden binärdaten binär übertragen. Andernfalls
werden sie zuerst in Textdaten umgewandelt und als Textdaten in die
Soap- Nachruichten eingebettet.
Windows
Dienst als Webservice Host
Webservices werden gewöhnlich unter ASP.NET
auf einem IIS ausgeführt. WSE 3.0 ermöglicht Webdienste
durch Programme oder Windowsdienste zu hosten. Jedoch ist dies
derzeit nur auf das TCP- Protokoll mit SOAP beschränkt.
Jeder Webservice ist ein SoapReceiver. Die
Menge aller Soap-Receiver, die eine Anwendung oder Dienst
bereitstellt, müssen mit der Klasse SoapReceivers in WSE
3.0 registriert werden. Dabei wird jedem Receiver eine sog.
EndpointReference zugeordnet. Eine EndpointReference ist eine
gegenüber WSDL reduzierte Dienstbeschreibung, die im
wesentlichen den Uri des Webdienstes definiert.

Wird ein Windows- Dienst als Host gewählt,
dann müssen in seine Assembly die WebService- Typen aufgenommen
werden (Hinzufügen der Quellcodes vom Webservice zum
Windowsdienst). Im Start- Eventhandler des Dienstes muß den
sog. SoapReceivers der Typ des Webservices und der Uri, unter
dem er erreichbar sein soll, hinzugefügt werden.
protected override void OnStart(string[] args)
{
// TODO: Hier Code hinzufügen, um den Dienst zu starten.
Uri address = new Uri("soap.tcp://localhost/TestService");
SoapReceivers.Add(new EndpointReference(address), typeof(Service));
log.LogMsg(0, "Wse30StandAloneWebservice gestartet");
}
protected override void OnStop()
{
// TODO: Hier Code zum Ausführen erforderlicher Löschvorgänge zum Anhalten des Dienstes hinzufügen.
SoapReceivers.Clear();
log.LogMsg(0, "Wse30StandAloneWebservice gestoppt");
}
Wenn der Dienst installiert und gestartet wird,
ist der Webservice verfügbar. Eine Proxyklasse kann dann auf dem
Client z.B. mittels
c:\WseWsdl3 soap.tcp://localhost/SimpleServicePolicy/Service.asmx /type:webClient /l:CS /n:Wse30Services
erstellt werden. WseWsdl3.exe ist ein spezielles wsdl- Tool für
WSE3.0 Dienste.
Sichern von Webdiensten durch Verschlüsseln von Soap Nachrichten
Probleme mit WSE
3.0
Fehler
|
Beschreibung
|
Workarround
|
WseWsdl3 erzeugt keine
Microsoft.Web.Services3. WebServicesClientProtocol
Proxys
|
Wird ein Proxy
für einen WSEService, der in einem Windowsdienst gehostet
wird, z.B. durch wsewsdl3
soap.tcp://localhost/TestSvr /type:webClient
erstellt, dann ist der Proxy von der Basisklasse
System.Web.Services.Protocols.SoapHttpClientProtocol
abgeleitet. Eine Verbindung mit dem Webservice über
soap.tcp- Protokoll ist mit diesem Proxy nicht möglich
|
Austauschen der Basisklasse
System.Web.Services.Protocols.SoapHttpClientProtocol
gegen Microsoft.Web.Services3. WebServicesClientProtocol
|
Keine Konfigurationstools im
Kontextmenü von Visual Studio
|
|
Aufruf des Konfigurationstools aus
Start/Programme/Microsoft WSE/ConfigurationTool und öffnen
der betreffenden Web.config über das Menü Datei
|
WCF-Service
In WCF wird ein Dienst in der Regel durch eine
Schnittstelle definiert, und durch eine Klasse implementiert. Die
Schnittstelle wird dabei als Servicecontract
bezeichnet.
Der
Servicekontract legt die abrufbaren Leistungen eines Dienstes fest.
Jede Leistung wird durch eine Mehtode beschrieben, die mit dem
Attribut OperationContract gekennzeichnet
ist.

Endpunkte
Die Kommunikation
zwischen einem Client und einem Server wird in WCF durch Endpunkte
definiert. Endpunkte legen fest,
Wo ein
Dienst zu finden ist (Adresse)
Was der
Dienst für eine Funktionalität anbietet (ServiceContract)
Wie der
Client mit dem Server kommunizieren kann (Bindung)
Die Definition
von Endpunkten bilden in WCF damit den Kern der Infrastruktur.

Bindungen
Bindungen definieren das Transportprotokoll (z.B.
HTTP) und die Kodierung (z.B. Text/XML).
WCF liefert schon eine Reihe vordefinierter
Bindungen: