Verwenden eines ASP.NET-Webdiensts (ASMX)
ASMX bietet die Möglichkeit, Webdienste zu erstellen, die Nachrichten mithilfe des Simple Object Access Protocol (SOAP) senden. SOAP ist ein plattformunabhängiges und sprachunabhängiges Protokoll zum Erstellen und Zugreifen auf Webdienste. Consumer eines ASMX-Diensts müssen nichts über die Plattform, das Objektmodell oder die Programmiersprache wissen, die zum Implementieren des Diensts verwendet wird. Sie müssen nur verstehen, wie SOAP-Nachrichten gesendet und empfangen werden. In diesem Artikel wird veranschaulicht, wie Sie einen ASMX-SOAP-Dienst aus einer Xamarin.Forms Anwendung nutzen.
Eine SOAP-Nachricht ist ein XML-Dokument, das die folgenden Elemente enthält:
- Ein Stammelement namens Envelope , das das XML-Dokument als SOAP-Nachricht identifiziert.
- Ein optionales Header-Element , das anwendungsspezifische Informationen wie Authentifizierungsdaten enthält. Wenn das Header-Element vorhanden ist, muss es das erste untergeordnete Element des Envelope-Elements sein.
- Ein erforderliches Body-Element , das die SOAP-Nachricht enthält, die für den Empfänger vorgesehen ist.
- Ein optionales Fault-Element , das verwendet wird, um Fehlermeldungen anzuzeigen. Wenn das Fault-Element vorhanden ist, muss es ein untergeordnetes Element des Body-Elements sein.
SOAP kann über viele Transportprotokolle ausgeführt werden, einschließlich HTTP, SMTP, TCP und UDP. Ein ASMX-Dienst kann jedoch nur über HTTP betrieben werden. Die Xamarin-Plattform unterstützt SOAP 1.1-Standardimplementierungen über HTTP, und dies schließt die Unterstützung für viele der Standardmäßigen ASMX-Dienstkonfigurationen ein.
Dieses Beispiel umfasst die mobilen Anwendungen, die auf physischen oder emulierten Geräten ausgeführt werden, sowie einen ASMX-Dienst, der Methoden zum Abrufen, Hinzufügen, Bearbeiten und Löschen von Daten bereitstellt. Wenn die mobilen Anwendungen ausgeführt werden, stellen sie eine Verbindung mit dem lokal gehosteten ASMX-Dienst her, wie 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 und verhindert so die versehentliche Offenlegung vertraulicher Informationen. Da ATS in Apps, die für iOS 9 erstellt wurden, standardmäßig aktiviert ist, unterliegen alle Verbindungen den ATS-Sicherheitsanforderungen. Wenn Verbindungen diese Anforderungen nicht erfüllen, schlagen sie mit einer Ausnahme fehl.
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 Datei Info.plist der App erreicht werden. Weitere Informationen finden Sie unter App Transport Security.
Nutzen des Webdiensts
Der ASMX-Dienst stellt die folgenden Vorgänge bereit:
Vorgang | BESCHREIBUNG | Parameter |
---|---|---|
GetTodoItems | Abrufen einer Liste von To-Do-Elementen | |
CreateTodoItem | Erstellen eines neuen To-Do-Elements | Ein xml serialisiertes TodoItem |
EditTodoItem | Aktualisieren eines To-Do-Elements | Ein xml serialisiertes TodoItem |
DeleteTodoItem | Löschen eines To-Do-Elements | Ein xml serialisiertes TodoItem |
Weitere Informationen zum in der Anwendung verwendeten Datenmodell finden Sie unter Modellieren der Daten.
Erstellen des TodoService-Proxys
Eine Proxyklasse namens TodoService
erweitert SoapHttpClientProtocol
und stellt Methoden für die Kommunikation mit dem ASMX-Dienst über HTTP bereit. Der Proxy wird generiert, indem jedem plattformspezifischen Projekt in Visual Studio 2019 oder Visual Studio 2017 ein Webverweis hinzugefügt wird. Der Webverweis generiert Methoden und Ereignisse für jede Aktion, die im WSDL-Dokument (Web Services Description Language) des Diensts definiert ist.
Beispielsweise führt die GetTodoItems
Dienstaktion zu einer GetTodoItemsAsync
Methode und einem GetTodoItemsCompleted
Ereignis im Proxy. Die generierte Methode verfügt über einen void-Rückgabetyp und ruft die GetTodoItems
Aktion für die übergeordnete SoapHttpClientProtocol
Klasse auf. Wenn die aufgerufene Methode eine Antwort vom Dienst empfängt, löst sie das GetTodoItemsCompleted
-Ereignis aus und stellt die Antwortdaten innerhalb der -Eigenschaft des Ereignisses Result
bereit.
Erstellen der ISoapService-Implementierung
Damit das freigegebene, plattformübergreifende Projekt mit dem Dienst funktioniert, definiert das Beispiel die ISoapService
Schnittstelle, die dem asynchronen Programmiermodell der Aufgabe in C# folgt. Jede Plattform implementiert den ISoapService
, um den plattformspezifischen Proxy verfügbar zu machen. Im Beispiel werden Objekte verwendet TaskCompletionSource
, um den Proxy als asynchrone Taskschnittstelle verfügbar zu machen. Details zur Verwendung TaskCompletionSource
finden Sie in den Implementierungen der einzelnen Aktionstypen in den folgenden Abschnitten.
Das Beispiel SoapService
:
- Instanziiert den
TodoService
als instance auf Klassenebene - Erstellt eine Auflistung namens
Items
zum Speichern vonTodoItem
Objekten. - Gibt einen benutzerdefinierten Endpunkt für die optionale
Url
Eigenschaft für dieTodoService
public class SoapService : ISoapService
{
ASMXService.TodoService todoService;
public List<TodoItem> Items { get; private set; } = new List<TodoItem>();
public SoapService ()
{
todoService = new ASMXService.TodoService ();
todoService.Url = Constants.SoapUrl;
...
}
}
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 proxygenerierten TodoItem
Typ konvertiert werden. Dies wird durch die ToASMXServiceTodoItem
-Methode erreicht, wie im folgenden Codebeispiel gezeigt:
ASMXService.TodoItem ToASMXServiceTodoItem (TodoItem item)
{
return new ASMXService.TodoItem {
ID = item.ID,
Name = item.Name,
Notes = item.Notes,
Done = item.Done
};
}
Diese Methode erstellt eine neue ASMService.TodoItem
instance und legt jede Eigenschaft auf die identische Eigenschaft aus dem TodoItem
instance fest.
Ebenso müssen Daten beim Abrufen aus dem Webdienst vom proxygenerierten TodoItem
Typ in einen TodoItem
instance konvertiert werden. Dies wird mit der FromASMXServiceTodoItem
-Methode erreicht, wie im folgenden Codebeispiel gezeigt:
static TodoItem FromASMXServiceTodoItem (ASMXService.TodoItem item)
{
return new TodoItem {
ID = item.ID,
Name = item.Name,
Notes = item.Notes,
Done = item.Done
};
}
Diese Methode ruft die Daten aus dem vom Proxy generierten TodoItem
Typ ab und legt sie im neu erstellten TodoItem
instance fest.
Abrufen von Daten
Die ISoapService
-Schnittstelle erwartet, dass die RefreshDataAsync
-Methode eine Task
mit der Elementauflistung zurückgibt. Die TodoService.GetTodoItemsAsync
Methode gibt jedoch void zurück. Um das Schnittstellenmuster zu erfüllen, müssen Sie aufrufen GetTodoItemsAsync
, warten, bis das GetTodoItemsCompleted
Ereignis ausgelöst wird, und die Auflistung auffüllen. Dadurch können Sie eine gültige Sammlung an die Benutzeroberfläche zurückgeben.
Im folgenden Beispiel wird ein neues TaskCompletionSource
erstellt, beginnt den asynchronen Aufruf in der RefreshDataAsync
-Methode und wartet auf das Task
vom bereitgestellte TaskCompletionSource
. Wenn der TodoService_GetTodoItemsCompleted
Ereignishandler aufgerufen wird, füllt er die Items
Auflistung auf und aktualisiert :TaskCompletionSource
public class SoapService : ISoapService
{
TaskCompletionSource<bool> getRequestComplete = null;
...
public SoapService()
{
...
todoService.GetTodoItemsCompleted += TodoService_GetTodoItemsCompleted;
}
public async Task<List<TodoItem>> RefreshDataAsync()
{
getRequestComplete = new TaskCompletionSource<bool>();
todoService.GetTodoItemsAsync();
await getRequestComplete.Task;
return Items;
}
private void TodoService_GetTodoItemsCompleted(object sender, ASMXService.GetTodoItemsCompletedEventArgs e)
{
try
{
getRequestComplete = getRequestComplete ?? new TaskCompletionSource<bool>();
Items = new List<TodoItem>();
foreach (var item in e.Result)
{
Items.Add(FromASMXServiceTodoItem(item));
}
getRequestComplete?.TrySetResult(true);
}
catch (Exception ex)
{
Debug.WriteLine(@"\t\tERROR {0}", ex.Message);
}
}
...
}
Weitere Informationen finden Sie unter Asynchrones Programmiermodell und TPL und herkömmliche .NET Framework asynchrone Programmierung.
Erstellen oder Bearbeiten von Daten
Wenn Sie Daten erstellen oder bearbeiten, müssen Sie die ISoapService.SaveTodoItemAsync
-Methode implementieren. Diese Methode erkennt, ob es sich um TodoItem
ein neues oder aktualisiertes Element handelt, und ruft die entsprechende Methode für das todoService
-Objekt auf. Die CreateTodoItemCompleted
Ereignishandler und EditTodoItemCompleted
sollten auch implementiert werden, damit Sie wissen, wann eine todoService
Antwort vom ASMX-Dienst empfangen wurde (diese können in einem einzelnen Handler kombiniert werden, da sie denselben Vorgang ausführen). Im folgenden Beispiel werden die Schnittstellen- und Ereignishandlerimplementierungen sowie das -Objekt veranschaulicht, das TaskCompletionSource
zum asynchronen Betrieb verwendet wird:
public class SoapService : ISoapService
{
TaskCompletionSource<bool> saveRequestComplete = null;
...
public SoapService()
{
...
todoService.CreateTodoItemCompleted += TodoService_SaveTodoItemCompleted;
todoService.EditTodoItemCompleted += TodoService_SaveTodoItemCompleted;
}
public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
{
try
{
var todoItem = ToASMXServiceTodoItem(item);
saveRequestComplete = new TaskCompletionSource<bool>();
if (isNewItem)
{
todoService.CreateTodoItemAsync(todoItem);
}
else
{
todoService.EditTodoItemAsync(todoItem);
}
await saveRequestComplete.Task;
}
catch (SoapException se)
{
Debug.WriteLine("\t\t{0}", se.Message);
}
catch (Exception ex)
{
Debug.WriteLine("\t\tERROR {0}", ex.Message);
}
}
private void TodoService_SaveTodoItemCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
saveRequestComplete?.TrySetResult(true);
}
...
}
Löschen von Daten
Das Löschen von Daten erfordert eine ähnliche Implementierung. Definieren Sie eine TaskCompletionSource
, implementieren Sie einen Ereignishandler und die ISoapService.DeleteTodoItemAsync
-Methode:
public class SoapService : ISoapService
{
TaskCompletionSource<bool> deleteRequestComplete = null;
...
public SoapService()
{
...
todoService.DeleteTodoItemCompleted += TodoService_DeleteTodoItemCompleted;
}
public async Task DeleteTodoItemAsync (string id)
{
try
{
deleteRequestComplete = new TaskCompletionSource<bool>();
todoService.DeleteTodoItemAsync(id);
await deleteRequestComplete.Task;
}
catch (SoapException se)
{
Debug.WriteLine("\t\t{0}", se.Message);
}
catch (Exception ex)
{
Debug.WriteLine("\t\tERROR {0}", ex.Message);
}
}
private void TodoService_DeleteTodoItemCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
deleteRequestComplete?.TrySetResult(true);
}
...
}
Testen des Webdiensts
Zum Testen physischer oder emulierter Geräte mit einem lokal gehosteten Dienst müssen benutzerdefinierte IIS-Konfiguration, Endpunktadressen und Firewallregeln vorhanden sein. Weitere Informationen zum Einrichten Ihrer Umgebung für Tests finden Sie unter Konfigurieren des Remotezugriffs auf IIS Express. Der einzige Unterschied zwischen dem Testen von WCF und ASMX ist die Portnummer des TodoService.