Verwenden eines Wcf-Webdiensts (Windows Communication Foundation)
WCF ist das einheitliche Framework von Microsoft zum Erstellen dienstorientierter Anwendungen. Es ermöglicht Entwicklern, sichere, zuverlässige, transaktionen und interoperable verteilte Anwendungen zu erstellen. In diesem Artikel wird veranschaulicht, wie Sie einen SOAP-Dienst (Simple Object Access Protocol) von einer Xamarin.Forms Anwendung nutzen.
WCF beschreibt einen Dienst mit einer Vielzahl verschiedener Verträge, einschließlich:
- Datenverträge – definieren Sie die Datenstrukturen, die die Grundlage für den Inhalt innerhalb einer Nachricht bilden.
- Nachrichtenverträge – Nachrichten aus vorhandenen Datenverträgen verfassen.
- Fehlerverträge – die Angabe benutzerdefinierter SOAP-Fehler zulassen.
- Serviceverträge – Geben Sie die Vorgänge an, die dienste unterstützen, und die nachrichten, die für die Interaktion mit den einzelnen Vorgängen erforderlich sind. Sie geben auch ein benutzerdefiniertes Fehlerverhalten an, das Vorgängen für jeden Dienst zugeordnet werden kann.
Es gibt Unterschiede zwischen ASP.NET Webdiensten (ASMX) und WCF, aber WCF unterstützt dieselben Funktionen wie ASMX – SOAP-Nachrichten über HTTP. Weitere Informationen zum Verwenden eines ASMX-Diensts finden Sie unter "Nutzen ASP.NET Webdienste (ASMX)".
Wichtig
Die Xamarin-Plattformunterstützung für WCF ist auf textcodierte SOAP-Nachrichten über HTTP/HTTPS mit der BasicHttpBinding
Klasse beschränkt.
Die WCF-Unterstützung erfordert die Verwendung von Tools, die nur in einer Windows-Umgebung verfügbar sind, um den Proxy zu generieren und den TodoWCFService zu hosten. Das Erstellen und Testen der iOS-App erfordert die Bereitstellung des TodoWCFService auf einem Windows-Computer oder als Azure-Webdienst.
Xamarin Forms native Apps teilen in der Regel Code mit einer .NET Standard Class Library. .NET Core unterstützt derzeit jedoch nicht WCF, sodass das freigegebene Projekt eine ältere portable Klassenbibliothek sein muss. Informationen zur WCF-Unterstützung in .NET Core finden Sie unter Auswählen zwischen .NET Core und .NET Framework für Server-Apps.
Die Beispielanwendungslösung enthält einen WCF-Dienst, der lokal ausgeführt werden kann, und wird im folgenden Screenshot gezeigt:
Hinweis
In iOS 9 und höher erzwingt App Transport Security (ATS) sichere Verbindungen zwischen Internetressourcen (z. B. dem Back-End-Server der App) und der App, wodurch die versehentliche Offenlegung vertraulicher Informationen verhindert wird. Da ATS standardmäßig in Apps aktiviert ist, die für iOS 9 erstellt wurden, unterliegen alle Verbindungen den ATS-Sicherheitsanforderungen. Wenn Verbindungen diese Anforderungen nicht erfüllen, tritt ein Ausnahmefehler auf.
ATS kann deaktiviert werden, wenn es nicht möglich ist, das Protokoll und die HTTPS
sichere Kommunikation für Internetressourcen zu verwenden. Dies kann durch Aktualisieren der Info.plist-Datei der App erreicht werden. Weitere Informationen finden Sie unter App Transport Security.
Nutzen des Webdiensts
Der WCF-Dienst stellt die folgenden Vorgänge bereit:
Vorgang | Beschreibung | Parameter |
---|---|---|
GetTodoItems | Abrufen einer Liste von To-Do-Elementen | |
CreateTodoItem | Erstellen eines neuen Aufgabenelements | Ein serialisiertes XML-TodoItem |
EditTodoItem | Aktualisieren eines To-Do-Elements | Ein serialisiertes XML-TodoItem |
DeleteTodoItem | Löschen eines To-Do-Elements | Ein serialisiertes XML-TodoItem |
Weitere Informationen zum in der Anwendung verwendeten Datenmodell finden Sie unter Modellieren der Daten.
Ein Proxy muss generiert werden, um einen WCF-Dienst zu nutzen, der es der Anwendung ermöglicht, eine Verbindung mit dem Dienst herzustellen. Der Proxy wird erstellt, indem Dienstmetadaten verwendet werden, die die Methoden und die zugehörige Dienstkonfiguration definieren. Diese Metadaten werden in Form eines WSDL-Dokuments (Web Services Description Language) verfügbar gemacht, das vom Webdienst generiert wird. Der Proxy kann mithilfe des Microsoft WCF-Webdienstverweisanbieters in Visual Studio 2017 erstellt werden, um einer .NET Standard-Bibliothek einen Dienstverweis für den Webdienst hinzuzufügen. Eine Alternative zum Erstellen des Proxys mithilfe des Microsoft WCF-Webdienstverweisanbieters in Visual Studio 2017 besteht darin, das ServiceModel Metadata Utility Tool (svcutil.exe) zu verwenden. Weitere Informationen finden Sie unter ServiceModel Metadata Utility Tool (Svcutil.exe).For more information, see ServiceModel Metadata Utility Tool (Svcutil.exe).
Die generierten Proxyklassen stellen Methoden für die Verwendung der Webdienste bereit, die das APM-Entwurfsmuster (Asynchronous Programming Model) verwenden. In diesem Muster wird ein asynchroner Vorgang als zwei Methoden namens "BeginOperationName" und "EndOperationName" implementiert, die den asynchronen Vorgang beginnen und beenden.
Die BeginOperationName-Methode beginnt den asynchronen Vorgang und gibt ein Objekt zurück, das die IAsyncResult
Schnittstelle implementiert. Nach dem Aufrufen von BeginOperationName kann eine Anwendung die Ausführung von Anweisungen für den aufrufenden Thread fortsetzen, während der asynchrone Vorgang in einem Threadpoolthread stattfindet.
Für jeden Aufruf von BeginOperationName sollte die Anwendung auch EndOperationName aufrufen, um die Ergebnisse des Vorgangs abzurufen. Der Rückgabewert von EndOperationName ist derselbe Typ, der von der synchronen Webdienstmethode zurückgegeben wird. Die Methode gibt beispielsweise EndGetTodoItems
eine Auflistung von TodoItem
Instanzen zurück. Die EndOperationName-Methode enthält auch einen IAsyncResult
Parameter, der auf die Instanz festgelegt werden soll, die vom entsprechenden Aufruf der BeginOperationName-Methode zurückgegeben wird.
Die Task Parallel Library (TPL) kann den Prozess der Verwendung eines APM-Anfangs-/End-Methodenpaars vereinfachen, indem die asynchronen Vorgänge im selben Task
Objekt gekapselt werden. Diese Kapselung wird durch mehrere Überladungen der TaskFactory.FromAsync
Methode bereitgestellt.
Weitere Informationen zu APM finden Sie unter asynchrones Programmiermodell und TPL und herkömmliche .NET Framework-asynchrone Programmierung auf MSDN.
Erstellen des TodoServiceClient-Objekts
Die generierte Proxyklasse stellt die TodoServiceClient
Klasse bereit, die für die Kommunikation mit dem WCF-Dienst über HTTP verwendet wird. Sie stellt Funktionen zum Aufrufen von Webdienstmethoden als asynchrone Vorgänge aus einer identifizierten URI-Dienstinstanz bereit. Weitere Informationen zu asynchronen Vorgängen finden Sie unter Async Support Overview.
Die TodoServiceClient
Instanz wird auf Klassenebene deklariert, sodass das Objekt so lange lebt, wie im folgenden Codebeispiel gezeigt, dass die Anwendung den WCF-Dienst nutzen muss:
public class SoapService : ISoapService
{
ITodoService todoService;
...
public SoapService ()
{
todoService = new TodoServiceClient (
new BasicHttpBinding (),
new EndpointAddress (Constants.SoapUrl));
}
...
}
Die TodoServiceClient
Instanz ist mit Bindungsinformationen und einer Endpunktadresse konfiguriert. Eine Bindung wird verwendet, um die Transport-, Codierungs- und Protokolldetails anzugeben, die für Anwendungen und Dienste erforderlich sind, um miteinander zu kommunizieren. Dies BasicHttpBinding
gibt an, dass textcodierte SOAP-Nachrichten über das HTTP-Transportprotokoll gesendet werden. Wenn Sie eine Endpunktadresse angeben, kann die Anwendung eine Verbindung mit verschiedenen Instanzen des WCF-Diensts herstellen, vorausgesetzt, es gibt mehrere veröffentlichte Instanzen.
Weitere Informationen zum Konfigurieren der Dienstreferenz finden Sie unter Konfigurieren der Dienstreferenz.
Erstellen von Datenübertragungsobjekten
Die Beispielanwendung verwendet die TodoItem
Klasse zum Modellieren von Daten. Um ein TodoItem
Element im Webdienst zu speichern, muss es zuerst in den generierten TodoItem
Proxytyp konvertiert werden. Dies wird durch die ToWCFServiceTodoItem
Methode erreicht, wie im folgenden Codebeispiel gezeigt:
TodoWCFService.TodoItem ToWCFServiceTodoItem (TodoItem item)
{
return new TodoWCFService.TodoItem
{
ID = item.ID,
Name = item.Name,
Notes = item.Notes,
Done = item.Done
};
}
Diese Methode erstellt einfach eine neue TodoWCFService.TodoItem
Instanz und legt jede Eigenschaft auf die identische Eigenschaft aus der TodoItem
Instanz fest.
Wenn Daten aus dem Webdienst abgerufen werden, muss sie auch vom generierten TodoItem
Proxytyp in eine TodoItem
Instanz konvertiert werden. Dies erfolgt mit der FromWCFServiceTodoItem
Methode, wie im folgenden Codebeispiel gezeigt:
static TodoItem FromWCFServiceTodoItem (TodoWCFService.TodoItem item)
{
return new TodoItem
{
ID = item.ID,
Name = item.Name,
Notes = item.Notes,
Done = item.Done
};
}
Diese Methode ruft einfach die Daten aus dem generierten TodoItem
Proxytyp ab und legt sie in der neu erstellten TodoItem
Instanz fest.
Abrufen von Daten
Die TodoServiceClient.BeginGetTodoItems
Methoden und TodoServiceClient.EndGetTodoItems
Methoden werden verwendet, um den GetTodoItems
vom Webdienst bereitgestellten Vorgang aufzurufen. Diese asynchronen Methoden werden in einem Task
Objekt gekapselt, wie im folgenden Codebeispiel gezeigt:
public async Task<List<TodoItem>> RefreshDataAsync ()
{
...
var todoItems = await Task.Factory.FromAsync <ObservableCollection<TodoWCFService.TodoItem>> (
todoService.BeginGetTodoItems,
todoService.EndGetTodoItems,
null,
TaskCreationOptions.None);
foreach (var item in todoItems)
{
Items.Add (FromWCFServiceTodoItem (item));
}
...
}
Die Task.Factory.FromAsync
Methode erstellt eine Task
Methode, die die TodoServiceClient.EndGetTodoItems
Methode nach Abschluss der TodoServiceClient.BeginGetTodoItems
Methode ausführt, wobei der null
Parameter angibt, dass keine Daten an den BeginGetTodoItems
Delegaten übergeben werden. Schließlich gibt der Wert der TaskCreationOptions
Enumeration an, dass das Standardverhalten für die Erstellung und Ausführung von Aufgaben verwendet werden soll.
Die TodoServiceClient.EndGetTodoItems
Methode gibt eine ObservableCollection
Instanz zurück TodoWCFService.TodoItem
, die dann für die Anzeige in eine List
Instanz TodoItem
konvertiert wird.
Daten erstellen
Die TodoServiceClient.BeginCreateTodoItem
Methoden und TodoServiceClient.EndCreateTodoItem
Methoden werden verwendet, um den CreateTodoItem
vom Webdienst bereitgestellten Vorgang aufzurufen. Diese asynchronen Methoden werden in einem Task
Objekt gekapselt, wie im folgenden Codebeispiel gezeigt:
public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
{
...
var todoItem = ToWCFServiceTodoItem (item);
...
await Task.Factory.FromAsync (
todoService.BeginCreateTodoItem,
todoService.EndCreateTodoItem,
todoItem,
TaskCreationOptions.None);
...
}
Die Task.Factory.FromAsync
Methode erstellt eine Task
Methode, die die TodoServiceClient.EndCreateTodoItem
Methode nach Abschluss der TodoServiceClient.BeginCreateTodoItem
Methode ausführt, wobei der todoItem
Parameter die Daten ist, die an den BeginCreateTodoItem
Delegaten übergeben werden, um den TodoItem
vom Webdienst zu erstellenden Wert anzugeben. Schließlich gibt der Wert der TaskCreationOptions
Enumeration an, dass das Standardverhalten für die Erstellung und Ausführung von Aufgaben verwendet werden soll.
Der Webdienst löst einen FaultException
Fall aus, wenn der Von der Anwendung behandelte Fehler beim Erstellen des TodoItem
Vom Webdienst verarbeiteten Fehlers auftritt.
Daten aktualisieren
Die TodoServiceClient.BeginEditTodoItem
Methoden und TodoServiceClient.EndEditTodoItem
Methoden werden verwendet, um den EditTodoItem
vom Webdienst bereitgestellten Vorgang aufzurufen. Diese asynchronen Methoden werden in einem Task
Objekt gekapselt, wie im folgenden Codebeispiel gezeigt:
public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
{
...
var todoItem = ToWCFServiceTodoItem (item);
...
await Task.Factory.FromAsync (
todoService.BeginEditTodoItem,
todoService.EndEditTodoItem,
todoItem,
TaskCreationOptions.None);
...
}
Die Task.Factory.FromAsync
Methode erstellt eine Task
Methode, die die TodoServiceClient.EndEditTodoItem
Methode nach Abschluss der TodoServiceClient.BeginCreateTodoItem
Methode ausführt, wobei der todoItem
Parameter die Daten ist, die an den BeginEditTodoItem
Delegaten übergeben werden, um die TodoItem
aktualisierung durch den Webdienst anzugeben. Schließlich gibt der Wert der TaskCreationOptions
Enumeration an, dass das Standardverhalten für die Erstellung und Ausführung von Aufgaben verwendet werden soll.
Der Webdienst löst einen FaultException
Fall aus, wenn er den TodoItem
von der Anwendung behandelten Fehler findet oder aktualisiert.
Löschen von Daten
Die TodoServiceClient.BeginDeleteTodoItem
Methoden und TodoServiceClient.EndDeleteTodoItem
Methoden werden verwendet, um den DeleteTodoItem
vom Webdienst bereitgestellten Vorgang aufzurufen. Diese asynchronen Methoden werden in einem Task
Objekt gekapselt, wie im folgenden Codebeispiel gezeigt:
public async Task DeleteTodoItemAsync (string id)
{
...
await Task.Factory.FromAsync (
todoService.BeginDeleteTodoItem,
todoService.EndDeleteTodoItem,
id,
TaskCreationOptions.None);
...
}
Die Task.Factory.FromAsync
Methode erstellt eine Task
Methode, die die TodoServiceClient.EndDeleteTodoItem
Methode nach Abschluss der TodoServiceClient.BeginDeleteTodoItem
Methode ausführt, wobei der id
Parameter die Daten ist, die an den BeginDeleteTodoItem
Delegaten übergeben werden, um anzugeben, dass die TodoItem
vom Webdienst gelöscht werden soll. Schließlich gibt der Wert der TaskCreationOptions
Enumeration an, dass das Standardverhalten für die Erstellung und Ausführung von Aufgaben verwendet werden soll.
Der Webdienst löst einen FaultException
Fall aus, wenn er das von der Anwendung behandelte Oder Löschen des TodoItem
Webdiensts nicht findet oder löscht.
Konfigurieren des Remotezugriffs auf IIS Express
In Visual Studio 2017 oder Visual Studio 2019 sollten Sie die UWP-Anwendung auf einem PC ohne zusätzliche Konfiguration testen können. Das Testen von Android- und iOS-Clients erfordert möglicherweise die zusätzlichen Schritte in diesem Abschnitt. Weitere Informationen finden Sie unter Verbinden zu lokalen Webdiensten von iOS Simulatoren und Android-Emulatoren.
Standardmäßig antwortet IIS Express nur auf Anforderungen an localhost
. Remotegeräte (z. B. Ein Android-Gerät, ein i Telefon oder sogar ein Simulator) haben keinen Zugriff auf Ihren lokalen WCF-Dienst. Sie müssen Ihre IP-Adresse der Windows 10-Arbeitsstation im lokalen Netzwerk kennen. Gehen Sie für dieses Beispiel davon aus, dass Ihre Arbeitsstation über die IP-Adresse 192.168.1.143
verfügt. In den folgenden Schritten wird erläutert, wie Windows 10 und IIS Express so konfiguriert werden, dass Remoteverbindungen akzeptiert und eine Verbindung mit dem Dienst von einem physischen oder virtuellen Gerät hergestellt wird:
Fügen Sie eine Ausnahme zur Windows-Firewall hinzu. Sie müssen einen Port über die Windows-Firewall öffnen, über den Anwendungen in Ihrem Subnetz für die Kommunikation mit dem WCF-Dienst verwendet werden können. Erstellen Sie eine eingehende Regel zum Öffnen von Port 49393 in der Firewall. Führen Sie an einer Administratorbefehlsaufforderung den folgenden Befehl aus:
netsh advfirewall firewall add rule name="TodoWCFService" dir=in protocol=tcp localport=49393 profile=private remoteip=localsubnet action=allow
Konfigurieren Sie IIS Express so, dass Remoteverbindungen akzeptiert werden. Sie können IIS Express konfigurieren, indem Sie die Konfigurationsdatei für IIS Express unter [Lösungsverzeichnis].vs\config\applicationhost.config bearbeiten. Suchen Sie das
site
Element mit dem NamenTodoWCFService
. Es sollte ähnlich wie die folgende XML aussehen:<site name="TodoWCFService" id="2"> <application path="/" applicationPool="Clr4IntegratedAppPool"> <virtualDirectory path="/" physicalPath="C:\Users\tom\TodoWCF\TodoWCFService\TodoWCFService" /> </application> <bindings> <binding protocol="http" bindingInformation="*:49393:localhost" /> </bindings> </site>
Sie müssen zwei
binding
Elemente hinzufügen, um Port 49393 außerhalb des Datenverkehrs und des Android-Emulators zu öffnen. Die Bindung verwendet ein[IP address]:[port]:[hostname]
Format, das angibt, wie IIS Express auf Anforderungen reagiert. Externe Anforderungen verfügen über Hostnamen, die als einebinding
angegeben werden müssen. Fügen Sie dembindings
Element den folgenden XML-Code hinzu, wobei die IP-Adresse durch Ihre eigene IP-Adresse ersetzt wird:<binding protocol="http" bindingInformation="*:49393:192.168.1.143" /> <binding protocol="http" bindingInformation="*:49393:127.0.0.1" />
Nach den Änderungen sollte das
bindings
Element wie folgt aussehen:<site name="TodoWCFService" id="2"> <application path="/" applicationPool="Clr4IntegratedAppPool"> <virtualDirectory path="/" physicalPath="C:\Users\tom\TodoWCF\TodoWCFService\TodoWCFService" /> </application> <bindings> <binding protocol="http" bindingInformation="*:49393:localhost" /> <binding protocol="http" bindingInformation="*:49393:192.168.1.143" /> <binding protocol="http" bindingInformation="*:49393:127.0.0.1" /> </bindings> </site>
Wichtig
Aus Sicherheitsgründen akzeptiert IIS Express standardmäßig keine Verbindungen von externen Quellen. Um Verbindungen von Remotegeräten zu aktivieren, müssen Sie IIS Express mit Administratorberechtigungen ausführen. Die einfachste Möglichkeit hierfür ist das Ausführen von Visual Studio 2017 mit Administratorberechtigungen. Dadurch wird IIS Express mit Administratorberechtigungen gestartet, wenn Der TodoWCFService ausgeführt wird.
Mit diesen Schritten sollten Sie in der Lage sein, todoWCFService auszuführen und von anderen Geräten in Ihrem Subnetz eine Verbindung herzustellen. Sie können dies testen, indem Sie Ihre Anwendung ausführen und besuchen
http://localhost:49393/TodoService.svc
. Wenn beim Aufrufen dieser URL eine Fehlermeldung "Ungültige Anforderung " angezeigt wird, ist Diesbindings
möglicherweise in der IIS Express-Konfiguration falsch (die Anforderung erreicht IIS Express, wird jedoch abgelehnt). Wenn sie einen anderen Fehler erhalten, kann es sein, dass Ihre Anwendung nicht ausgeführt wird oder Ihre Firewall falsch konfiguriert ist.Um IIS Express die Ausführung und Bereitstellung des Diensts zu ermöglichen, deaktivieren Sie die Option "Bearbeiten und Fortsetzen" in Project Properties-Webdebuggern >>.
Passen Sie die Endpunktgeräte an, die für den Zugriff auf den Dienst verwendet werden. Dieser Schritt umfasst das Konfigurieren der Clientanwendung, die auf einem physischen oder emulierten Gerät ausgeführt wird, um auf den WCF-Dienst zuzugreifen.
Der Android-Emulator verwendet einen internen Proxy, der verhindert, dass der Emulator direkt auf die Adresse des Hostcomputers
localhost
zugreift. Stattdessen wird die Adresse10.0.2.2
des Emulators über einen internen Proxy anlocalhost
den Hostcomputer weitergeleitet. Diese proxiierten Anforderungen haben127.0.0.1
den Hostnamen im Anforderungsheader, weshalb Sie in den obigen Schritten die IIS Express-Bindung für diesen Hostnamen erstellt haben.Der iOS Simulator wird auf einem Mac-Buildhost ausgeführt, auch wenn Sie den Remoted iOS Simulator für Windows verwenden. Netzwerkanforderungen vom Simulator verfügen über Ihre Arbeitsstations-IP im lokalen Netzwerk als Hostname (in diesem Beispiel ist
192.168.1.143
es, aber Ihre tatsächliche IP-Adresse wird wahrscheinlich anders sein). Aus diesem Grund haben Sie die IIS Express-Bindung für diesen Hostnamen in den obigen Schritten erstellt.Stellen Sie sicher, dass die
SoapUrl
Eigenschaft in der datei Constants.cs im Projekt TodoWCF (Portable) Werte aufweist, die für Ihr Netzwerk korrekt sind:public static string SoapUrl { get { var defaultUrl = "http://localhost:49393/TodoService.svc"; if (Device.RuntimePlatform == Device.Android) { defaultUrl = "http://10.0.2.2:49393/TodoService.svc"; } else if (Device.RuntimePlatform == Device.iOS) { defaultUrl = "http://192.168.1.143:49393/TodoService.svc"; } return defaultUrl; } }
Nachdem Sie die Constants.cs mit den entsprechenden Endpunkten konfiguriert haben, sollten Sie über physische oder virtuelle Geräte eine Verbindung mit dem TodoWCFService herstellen können, der auf Ihrer Windows 10-Arbeitsstation ausgeführt wird.