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:

Beispielanwendung

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 TodoItemVom 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 TodoItemvon 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 TodoItemWebdiensts 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.143verfü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:

  1. 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
    
  2. 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 Namen TodoWCFService. 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 eine bindingangegeben werden müssen. Fügen Sie dem bindings 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 Dies bindings 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 >>.

  3. 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 Adresse 10.0.2.2 des Emulators über einen internen Proxy an localhost den Hostcomputer weitergeleitet. Diese proxiierten Anforderungen haben 127.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.143es, 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.