Webdienste mit ASP.NET
Rob Howard
Microsoft Corporation
22. Februar 2001
Webdienste sind die Grundlage der .NET-Strategie von Microsoft. Die Konzepte und die Innovationen hinter dieser Initiative haben den Nerv getroffen, wenn Entwickler die nächste Generation von Internetanwendungen entwickeln.
In der Spalte dieses Monats werfen wir einen Blick auf die Features in ASP.NET, um Webdienste zu aktivieren. Bevor wir uns mit den technischen Details vertraut machen, beginnen wir mit einer Übersicht über Webdienste.
Übersicht über Webdienste
Ein Webdienst ist eine programmierbare Anwendungslogik, auf die über Standardwebprotokolle zugegriffen werden kann. Eines dieser Webprotokolle ist das Simple Object Access Protocol (SOAP). SOAP ist eine von W3C übermittelte Notiz (Stand: Mai 2000), die auf Standards basierende Technologien (XML für Datenbeschreibung und HTTP für den Transport) zum Codieren und Übertragen von Anwendungsdaten verwendet.
Consumer eines Webdiensts 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 (HTTP und XML) gesendet und empfangen werden.
Soap-Nachricht
Eine SOAP-Nachricht besteht aus mehreren Elementen, insbesondere einem Umschlag. Der Umschlag kapselt die daten, die innerhalb der SOAP-Nachricht übertragen werden. Im Folgenden finden Sie eine einfache SOAP-Nachricht mit HTTP-Headern:
POST /demo/MSDN/PerfCounter.asmx HTTP/1.1
Connection: Keep-Alive
Content-Length: 150
Content-Type: text/xml
Host: localhost
User-Agent: MS Web Services Client Protocol 1.0.2204.19
SOAPAction: "http://tempuri.org/PerfCounters"
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="https://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<soap:Body>
<PerfCounters xmlns="http://tempuri.org/"/>
</soap:Body>
</soap:Envelope>
Im obigen Beispiel sehen wir die HTTP-Header für die Anforderung, einschließlich des HTTP SOAPAction-Headers, der optional vom Server zum Weiterleiten der SOAP-Nachricht verwendet wird. Nach den HTTP-Headern finden wir den Text der HTTP-Nachricht. Der Text der HTTP-Nachricht ist die SOAP-Anforderung für einen PerfCounters-Webdienst, den wir erstellen werden.
Leider haben wir in dieser Spalte nicht fast genug Platz, um SOAP ausführlich zu diskutieren. Weitere Informationen zu SOAP finden Sie auf der Seite SOAP-Entwicklerressourcen. Hier finden Sie die öffentliche Spezifikation für SOAP 1.1 sowie Artikel und andere relevante Ressourcen.
ASP.NET-Webdienste
Webdienste sind einfach und leicht zu verstehen. Es ist in der Tat möglich, eine einfache Anwendung zu erstellen, die Daten als XML darstellt, die der SOAP-Spezifikation entspricht. Es wäre auch relativ einfach, eine Anwendung zu erstellen, die SOAP-Nachrichten über HTTP empfangen und daraus einen sinnvollen Wert ableiten kann. Für diejenigen, die mit PERL vertraut sind, könnte dies einfach eine Frage der Verwendung von RegEx sein, um den Wert aus dem XML-Ergebnis zu analysieren. es ist nur eine weitere Zeichenfolge.
So wie wir jedoch Frameworks wie ASP und ASP.NET verwenden, um Webanwendungen zu erstellen, würden wir viel lieber ein Framework für die Erstellung von Webdiensten verwenden. Die Begründung ist ziemlich logisch. Wir müssen die Sanitäranlagen nicht neu erfinden, d. h. auf hoher Ebene die Fähigkeit, unsere Daten als XML zu serialisieren, die Daten mithilfe von HTTP zu übertragen und die XML wieder in aussagekräftige Daten zu de serialisieren. Stattdessen wünschen wir uns ein Framework, das das Erstellen von Webdiensten vereinfacht, sodass wir uns auf die Anwendungslogik und nicht auf die Sanitäranlagen konzentrieren können. ASP.NET bietet uns diesen Rahmen.
Wenn Sie jemals Anwendungslogik geschrieben haben, verfügen Sie aus Entwicklersicht über die erforderlichen Fähigkeiten, um ASP.NET Webdienste zu erstellen. Wenn Sie überhaupt mit ASP- oder ASP.NET-Anwendungsdiensten (Anwendungszustandsspeicher usw.) vertraut sind, können Sie diese Fähigkeiten auch nutzen, wenn Sie ASP.NET Webdienste erstellen.
Verfügbarmachen
Zu diesem Beispiel schreiben wir einen Webdienst, der Leistungsindikatoren für Webanwendungen verfügbar macht. Leistungsindikatoren enthalten Details zum Verhalten unserer Anwendung, z. B. die Anzahl der aktiven Sitzungen oder die Anzahl der verarbeiteten Anforderungen. Wir haben nicht immer Zugriff auf einen lokalen Server auf unseren Webserver, und wenn wir über eine Serverfarm verfügen, möchten wir möglicherweise die Leistungsindikatoren von all diesen Servern verfügbar machen und sie an einem zentralen Ort aggregieren.
Beginnen Mit einem einfachen Beispiel
Anstatt direkt auf das Beispiel leistungsindikatoren zu springen, beginnen wir mit einer sehr einfachen Anwendungslogik, damit wir sehen können, was wir tun müssen, um unsere Logik als Webdienst verfügbar zu machen. Wir verwenden eine Add() -Methode, die zwei Ganze Zahlen akzeptiert und deren Summe zurückgibt. Im Folgenden finden Sie diese einfache Visual Basic-Logik:
Public Class MyMath
Public Function Add(a As Integer, b As Integer) As Integer
Return a + b
End Function
End Class
Wir können diese Klasse und ihre Methode wie folgt verwenden:
Dim mymath As new MyMath
Dim result As Integer
result = mymath.Add(10, 20)
Um die obige Klasse als ASP.NET Webdienst verfügbar zu machen, MyMath
müssen wir die Anwendungslogik in eine *.asmx-Datei verschieben. Genau wie wir die Erweiterung *.aspx für ASP.NET Pages verwenden, verwenden wir *.asmx, um ASP.NET mitzuteilen, dass es sich bei der Datei um einen ASP.NET Webdienst handelt.
Nachdem wir die *.asmx-Quelldatei erstellt und die Anwendungslogik hinzugefügt haben, müssen wir noch einige kleinere Änderungen vornehmen:
<%@ WebService Language="VB" Class="MyMath" %>
Public Class MyMath
Public Function <WebMethod()>Add(a As Integer, b As Integer) As Integer
Return a + b
End Function
End Class
Änderungen an unserer Quelle
Zu den Änderungen, die wir an der *.asmx-Datei vorgenommen haben, gehört das Hinzufügen einer WebService-Direktive , die sowohl den Language
als auch den benennt, den Class
wir als Webdienst verfügbar machen. Die WebService-Direktive ist erforderlich, da wir ASP.NET die Klasse angeben müssen, die die Anwendungslogik enthält. Als Nächstes haben wir der Add()-Funktionsdeklaration ein <WebMethod()> -Attribut hinzugefügt. Ein Attribut ist ein deklaratives Codeelement, mit dem wir das Verhalten der Anwendungslogik ändern können, ohne notwendigerweise mehr Code zu schreiben. Im Fall des <WebMethod()> -Attributs teilt dies ASP.NET mit, dass die Methode mit diesem Attribut als "Web callable" behandelt werden soll. Webaufrufbar in dem Sinne, dass ASP.NET die erforderliche Arbeit ausführt, damit diese Methode SOAP unterstützt.
Nachdem wir nun gesehen haben, was getan werden muss, um Anwendungslogik als webaufrufbar zu aktivieren, sehen wir uns ein relevanteres Beispiel an.
Leistungsindikatorwebdienst
Im Folgenden finden Sie eine Anwendungslogik, die uns Zugriff auf die Windows-Leistungsindikatoren® mit den Änderungen für ASP.NET Webdienste ermöglicht. Die Datei, die wir erstellt haben, ist PerfCounter.asmx:
<%@ WebService language="VB" class="PerfCounters" %>
Imports System.Xml.Serialization
Imports System.Web.Services
Imports System.Diagnostics
Public Class PerfCounters
Inherits WebService
' Returns a Counter class
Public Function <WebMethod()>GetCounters() As Counters
Dim c As new Counters
' Application Name
c.ApplicationName = IISAppName
' System specific
c.WorkerProcessRestarts = Poll(0, "Worker Process Restarts")
c.WorkerProcessRunning = Poll(0, "Worker Process Running")
c.ApplicationsRunning = Poll(0, "Applications Running")
c.RequestsQueued = Poll(0, "Requests Queued")
' Application Specific
c.RequestsTotal = Poll(1, "Requests Total")
c.RequestsFailed = Poll(1, "Requests Failed")
c.RequestsSucceeded = Poll(1, "Requests Succeeded")
c.ActiveSessions = Poll(1, "Sessions Active")
Return c
End Function
Private Function Poll(counterType As Integer, counter As String) As Integer
Dim PerfCounter As PerformanceCounter
If (counterType = 0)
PerfCounter = new PerformanceCounter("ASP Plus System", counter, "")
Else
PerfCounter = new PerformanceCounter("ASP Plus Applications", counter, IISAppName)
End If
Return PerfCounter.NextValue().ToInt32()
End Function
Private Function IISAppName() As String
Dim AppName As String
AppName = Context.Request.ServerVariables("APPL_MD_PATH")
AppName = AppName.Replace("/"C, "_"C)
Return AppName
End Function
End Class
Public Class Counters
Public ApplicationName As String
Public WorkerProcessRestarts As Integer
Public WorkerProcessRunning As Integer
Public ApplicationsRunning As Integer
Public RequestsQueued As Integer
Public RequestsTotal As Integer
Public RequestsFailed As Integer
Public RequestsSucceeded As Integer
Public ActiveSessions As Integer
End Class
Auch hier sehen wir, dass wir am Anfang der Datei eine WebService-Direktive deklariert haben, in der sowohl die Sprache als auch die Klasse angegeben werden. Die Klasse, die die aufrufbare Webmethode enthält, ist PerfCounters. Innerhalb von PerfCounters finden wir eine einzelne Methode, GetCounters(), mit dem <WebMethod()> -Attribut. GetCounters() gibt eine instance einer anderen Klasse zurück, Counters.
Wenn wir GetCounters() aufrufen, erstellt die Methode eine neue instance der Counter-Klasse und beginnt mit dem Festlegen der öffentlichen Member. Beachten Sie, dass diese öffentlichen Member als Eigenschaften implementiert werden sollten, aber ich habe mich entschieden, den Platz für den Zweck des Artikels zu sparen.
Wenn die Member der Counter-Klasse festgelegt sind, legen wir sie mit dem zurückgegebenen Ergebnis eines Aufrufs einer privaten Methode Poll() fest. Poll() ist für die eigentliche Arbeit beim Abrufen der Systemleistungsindikatoren und der Rückgabe eines Ergebnisses verantwortlich.
Schließlich gibt die letzte Methode, IISAppName(), den Wert der Servervariablen APPL_MD_PATH zurück und ersetzt "/"-Zeichen durch "_"-Zeichen. Dieser Wert wird als Anwendungsname innerhalb der Leistungsindikatoren verwendet.
Nachdem wir den Dienst erstellt haben, sehen wir uns nun an, wie wir ihn testen.
Testen von Webdiensten
Wie testen wir ihn nun, nachdem wir diesen ASP.NET Webdienst erstellt haben? Der Consumer eines Webdiensts ist eine andere Anwendung, aber ASP.NET stellt eine einfache Browserschnittstelle für unseren Webdienst bereit, die wir zu Test- oder Dokumentationszwecken verwenden können.
Da unser Dienst als Ressource verfügbar ist, die über unseren Webserver verfügbar ist, können wir einfach einen Browser öffnen und eine Anforderung für diese Ressource stellen. Auf diese Weise erhalten wir eine nette HTML-basierte Hilfeseite für Webdienste, auf der die Benutzer erfahren, was unser Dienst bietet:
Abbildung 1. HTML-basierte Webdienst-Hilfeseite
ASP.NET generiert die obige Seite für uns, und wir können sie verwenden, um unseren Dienst zu testen (beachten Sie die SCHALTFLÄCHE HTML-Aufruf im Abschnitt GetCounters Web Method) und auf die XML-Vertragssprache zugreifen, die verwendet wird, um zu beschreiben, was unser Dienst anbietet. Wir kehren zur XML-Vertragssprache zurück.
Wenn wir die Schaltfläche Aufrufen drücken, wird ein neues Browserfenster geöffnet, und es wird eine Anforderung an unseren Dienst über HTTP-Get gestellt. eines der drei unterstützten Protokolle, die von ASP.NET-Webdiensten verwendet werden:
Abbildung 2. Beispiel für das neue Browserfenster, das beim Drücken der Schaltfläche Aufrufen erstellt wird.
Der zurückgegebene XML-Code ist ein gültiges XML-Dokument, das alle Einstellungen beschreibt, die wir in unserer Counters-Klasse identifiziert haben. Es handelt sich jedoch nicht um SOAP. SOAP ist das Standardprotokoll, das bei der Kommunikation zwischen Anwendungen verwendet wird.
Obwohl wir dies in diesem Artikel nicht besprochen haben, können wir unsere Hilfeseite sehr umfangreich anpassen. Hierzu werden einige Änderungen am ASP.NET-Konfigurationssystem vorgenommen oder die DefaultSDLHelpGenerator.aspx geändert. Ich würde empfehlen, die DefaultSDLHelpGenerator.aspx nicht zu ändern, da dies die Vorlage ist, die für alle unsere Webdienste verwendet wird. Erstellen Sie stattdessen eine Kopie davon, und verweisen Sie auf die kopierte Version in der Konfiguration der Anwendung, die sie verwendet.
Nachdem wir nun das Erstellen und Testen unseres Webdiensts erläutert haben, nutzen wir ihn.
Verbrauchen
Wir haben mehrere Optionen für die Nutzung von Webdiensten. Da es in diesem Artikel um ASP.NET geht, konzentrieren wir uns auf .NET-Technologien, die Webdienste nutzen können. Ich sollte jedoch darauf hinweisen, dass jede Plattform oder jedes Framework, das SOAP versteht, in der Lage sein sollte, mit unserem Webdienst zu kommunizieren. Das Erstellen des Webdiensts mit ASP.NET bedeutet nicht, dass der Dienst nur für andere Microsoft-Anwendungen verfügbar ist.
Consumer eines Webdiensts müssen wissen, was der Dienst bietet, z. B. wie seine webaufrufbare Methode aussieht. Daher verwenden alle Webdienste optional ein anderes gemeinsames XML-Dokument: einen Vertrag (beachten Sie, dass mit ASP.NET erstellte Webdienste immer einen automatisch bereitgestellten Vertrag haben).
Vertrag
In den obigen Beispielen, als wir das Testen eines Webdiensts erläutert haben, haben wir den Link auf der Hilfeseite des Webdiensts nicht behandelt: SDL-Vertrag. Wenn wir diesem Link folgen würden, würde uns das folgende XML-Dokument angezeigt, anstatt die Schaltfläche Invoke für die GetCounters() -Webmethode zu drücken:
Abbildung 3. XML-Dokument, das beim Folgen des Links auf der Hilfeseite des Webdiensts angezeigt wird
Dieses XML-Dokument ist ein Vertrag, der unseren Webdienst beschreibt. Es werden die unterstützten Protokolle sowie die Semantik für das Aufrufen und Zurückgeben von Werten beschrieben. Außerdem wird ein XML-Schema für unsere Counters-Klasse definiert.
Tools können dieses XML-Schema verwenden, um Proxyklassen für unseren Webdienst zu erstellen. Eine Proxyklasse ist eine Klasse, die wie ein lokales Objekt aussieht und sich anfühlt, aber sie arbeitet tatsächlich daran, unsere Methodenanforderung an einen SOAP-Endpunkt zu serialisieren, zu senden, zu empfangen und zu de serialisieren.
Hinweis Beta 1 von .NET enthält einen "SDL–Service Description Language"-Vertrag. Beta 2 wechselt zur Verwendung des neueren "WSDL – Web Service Description Language"-Vertrags. Semantisch unterscheiden sie sich sehr. WSDL ist die Zusammenarbeit von Microsoft, IBM und mehreren anderen Unternehmen, um die XML-Vertragssprache besser zu standardisieren.
Wir haben verschiedene Optionen für die Nutzung von Webdiensten, aber ich möchte insbesondere drei nennen:
- Visual Studio .NET: Visual Studio .NET erstellt den Proxy aus SDL oder WSDL und fügt dem Projekt den entsprechenden Code hinzu. Dazu wählen Sie einfach Projekt | Webverweise und dann auf einen gültigen Vertrag verweisen. Beachten Sie, dass für Beta 1 der Vertrag SDL sein muss.
- Befehlszeilentools: Das .NET SDK wird mit einem Tool namens WebServiceUtil.exe ausgeliefert, das einen SDL-Vertrag akzeptiert und den Proxyquellcode für Visual Basic .NET, C# oder JScript.NET generieren kann.
- IE 5.5. Verhalten: – Ein browserspezifisches Verhalten, das eine umfassende Clientinteraktion mit SOAP-Endpunkten ermöglicht. Für diejenigen unter Ihnen, die mit Remoteskripting vertraut sind, werden Sie dies lieben! Weitere Informationen zum IE 5.5-Verhalten finden Sie unter WebService-Verhalten.
Leider haben wir nicht den Raum, diese drei Optionen im Detail zu diskutieren. Ich dachte jedoch, dass es sich lohnen würde, das Erstellen eines Proxys mit dem Befehlszeilentool kurz zu behandeln, da dies für diejenigen gilt, die .NET installiert haben; nicht nur diejenigen, die über Visual Studio .NET verfügen.
Befehlszeilentool
.NET, unabhängig davon, ob Sie es als Teil von Visual Studio .NET oder im .NET SDK installieren, enthält ein Befehlszeilenproxygenerierungstool namens WebServiceUtil.exe. Der Pfad zu diesem Befehlszeilentool sowie mehreren anderen Befehlszeilentools wird unserem Pfad hinzugefügt, als .NET installiert wurde.
WebServiceUtil.exe ermöglicht es uns, einen SDL oder Vertrag als eines der Befehlszeilenargumente zu benennen, und das Tool kann dann den Quellcode für einen Proxy für unseren Webdienst generieren.
Wenn wir beispielsweise das SDL aus unserem Beispiel PerfCounters.asmx speichern würden, könnten wir WebServiceUtil.exe verwenden, um einen Visual Basic .NET-Proxy für diesen Webdienst zu generieren:
WebServiceUtil.exe /command:proxy PerfCounter.sdl /language:VB
Dadurch wird eine Quelldatei PerfCounters.vb generiert, die wir jetzt kompilieren müssen.
Mithilfe des VB.NET-Befehlszeilencompilers vbc.exe können wir unsere VB-Quelldatei kompilieren:
vbc /t:library /r:system.web.dll /r:system.web.services.dll /r:system.xml.serialization.dll perfcounters.vb
Wir haben mit dem Befehlszeilencompiler angegeben, dass wir eine Bibliothek (DLL) anstelle einer ausführbaren Datei (exe) erstellen möchten, und zusätzlich zum Benennen der zu kompilierenden Quelldatei haben wir einige .NET-Assemblys (Bibliotheken, die Klassen enthalten, die unsere Quelldatei benötigt) als Argumente für den Compiler angegeben.
Das Ergebnis ist PerfCounters.dll, ein vollständiger Proxy für unseren PerfCounters.asmx-ASP.NET-Webdienst, den wir jetzt in .NET-Anwendungen verwenden können, um über SOAP mit unserem Webdienst zu kommunizieren.
Verwenden Sie diesen Proxy, um eine einfache ASP.NET Seite zu erstellen, die unseren Webdienst nutzt und verwendet.
Verwenden des Webdiensts
Zunächst müssen wir den kompilierten Proxy, der als Assembly bezeichnet wird, im Verzeichnis \bin einer Webanwendung bereitstellen. Obwohl wir die Bereitstellung von kompiliertem Code in dieser Spalte noch nicht erläutert haben (ein weiteres Thema für eine zukünftige Spalte), genügt es zu sagen, dass zum "Registrieren" einer Assembly im System einfach das Kopieren des *.dll in das Verzeichnis \bin einer Webanwendung erforderlich ist. Dies ist ein Feature von .NET, aber die Verwendung des Verzeichnisses \bin ist spezifisch für ASP.NET.
Zur Vereinfachung erstellen wir ein bin-Verzeichnis aus dem Stammverzeichnis des Servers, z. B. c:\inetpub\wwwroot\bin. Ein \bin-Verzeichnis muss in einem Anwendungsstamm vorhanden sein, entweder im Stammverzeichnis des Webs oder in einem Ordner, der in IIS als Anwendung gekennzeichnet ist.
Als Nächstes kopieren wir die Assembly PerfCounters.dll in unser Verzeichnis \bin. Wir können jetzt unsere ASP.NET-Seite erstellen, die wir in c:\inetpub\wwwroot bereitstellen. Wir nennen es PerfCountersConsume.aspx:
<Script runat="server">
Public Sub Page_Load(sender As Object, e As EventArgs)
Dim perfcounters As New PerfCounters
Dim counters As Counters
counters = perfcounters.GetCounters()
webapp.InnerHtml = counters.ApplicationName
restarts.InnerHtml = counters.WorkerProcessRestarts.ToString()
procrunning.InnerHtml = counters.WorkerProcessRunning.ToString()
apprunning.InnerHtml = counters.ApplicationsRunning.ToString()
queued.InnerHtml = counters.RequestsQueued.ToString()
totalrequests.InnerHtml = counters.RequestsTotal.ToString()
failedrequests.InnerHtml = counters.RequestsFailed.ToString()
succeededrequests.InnerHtml = counters.RequestsSucceeded.ToString()
activesessions.InnerHtml = counters.ActiveSessions.ToString()
End Sub
</Script>
Web Application: <B id="webapp" runat="server"/><BR>
Process Restarts: <B id="restarts" runat="server"/><BR>
Processes Running: <B id="procrunning" runat="server"/><BR>
Applications Running: <B id="apprunning" runat="server"/><BR>
Requests Queued: <B id="queued" runat="server"/><BR>
Requests Total: <B id="totalrequests" runat="server"/><BR>
Requests Failed: <B id="failedrequests" runat="server"/><BR>
Requests Succeeded: <B id="succeededrequests" runat="server"/><BR>
Active Sessions: <B id="activesessions" runat="server"/><BR>
Der obige Code erstellt eine instance unserer Proxyklasse PerfCounters (für uns verfügbar, da es sich um eine registrierte Assembly in unserem Verzeichnis \bin handelt) ruft die GetCounters()-Methode auf und gibt eine instance einer Counters-Klasse zurück. Anschließend verwenden wir die instance der Counters-Klasse( Counters), um ihre Membervariablen anzufordern und ASP.NET Serversteuerelemente aufzufüllen. Das Ergebnis ist unten:
Abbildung 4. ASP.NET-Serversteuerelemente
Zusammenfassung
Diese Spalte hat einen sehr allgemeinen Überblick über ASP.NET Webdienste. Es gibt einige Details, die wir entweder beschönigt oder überhaupt nicht behandelt haben, z. B. Sicherheit, Verwendung des Sitzungszustands, Erweiterungen usw. In der Spalte des nächsten Monats werden wir uns ein erweitertes Feature von ASP.NET Webdiensten ansehen, Erweiterungen, die wir zum Erstellen von Attributen verwenden können, mit denen wir die Anforderung/Antwort unseres ASP.NET-Webdiensts nachverfolgen können.
Rob Howard ist Programmmanager für ASP.NET im .NET Framework Team. Er verbringt jede Freizeit, die er hat, entweder mit seiner Familie oder fliegen angeln im Osten Washingtons.