SO WIRD'S GEMACHT: Verwenden der HTTP-Transports

Dieser Dokumentation für die Vorschau nur ist und in späteren Versionen geändert. Leere Themen wurden als Platzhalter eingefügt.]

Den HTTP-Transport können Sie um Anwendungen auf einem Gerät zu erstellen, die an einen Dienst Windows Communication Foundation (WCF) auf dem Desktop eine Verbindung herstellen.

Dieses Thema beschreibt, wie um den WCF-Dienst, Verbindungsgeräte behandeln zu konfigurieren und wie die Clientanwendung erstellen. Er erläutert die Unterschiede in WCF-Dienstkonfiguration und clientseitigen Programmierung, die Sie berücksichtigen müssen, damit von mobile Geräten eine Verbindung mit dem Dienst herstellen. Weitere Informationen zum Erstellen von WCF-Anwendungen für den Desktop finden Sie in der Getting Started Tutorial in der WCF-Dokumentation.

Den WCF-Dienst für den Desktop zu erstellen

  1. Erstellen Sie ein neues Webdienstprojekt.

  2. Ändern Sie die Web.config-Datei, wie im folgenden Beispiel gezeigt. Ändern Sie die folgenden Elemente und Attribute in der Datei:

    • Change the <endpoint>binding attribute value to "basicHttpBinding". .NET Compact Framework unterstützt Textcodierung, aber nicht binäre Codierung.

    • Ändern Sie das behaviorConfiguration Attribut zum Verweisen auf den neuen Namen Verhalten.

    • Ersetzen Sie das <behavior>-Element, wie im Beispiel dargestellt.

    • Wenn Sie den HTTP-Dienst-Handler in der Datei Web.config registrieren müssen, Hinzufügen eines neuen <system.WebServer>-Elements mit den Informationen im Beispiel dargestellt.

    <?xml version="1.0"?>
    
    <configuration xmlns="https://schemas.microsoft.com/.NetConfiguration/v2.0">
      <system.serviceModel>
        <services>
          <service name="CalculatorService" behaviorConfiguration="MyServiceTypeBehaviors">
            <endpoint contract="ICalculatorService" binding="basicHttpBinding"/>
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="MyServiceTypeBehaviors">
              <serviceMetadata httpGetEnabled="true" />
              <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    
      <system.web>
        <compilation debug="true"/>
      </system.web>
    
      <system.webServer>
        <handlers>
          <add name="HttpSvcHandler" path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" resourceType="Unspecified" />
        </handlers>
      </system.webServer>
    
    </configuration>
    
  3. Entfernen Sie in den Quellcode für den WCF-Dienst alle in der ServiceContractOperationContract Attribute aus dem Code angegebenen Parameter.

    Hinweis

    In diesem Beispiel implementiert keine Unterstützung für Parameter in Verträgen wie z. B. ServiceContract und OperationContract angegeben.Wenn Sie für diese Verträge Parameter Unterstützung benötigen, können Sie das WCF ServiceModel-Dienstprogramm Tool von .NET Compact Framework (NetCFSvcUtil.exe), um Clientcode generieren.Dieses Tool baut Unterstützung für viele dieser Parameter in Anwendungen, die auf der .NET Compact Framework basieren.NetCFSvcUtil.exe ist in der Power Toys für .NET Compact Frameworkverfügbar. Weitere Informationen finden Sie unter Power Toys für .NET Framework.

    Im folgende Beispiel zeigt den WCF-Dienst Quellcode für eine vereinfachte Rechneranwendung.

    <ServiceContract()>  _
    PublicInterface ICalculatorService
        <OperationContract()>  _
        Function Add(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDouble    '<OperationContract()>  _Function Subtract(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDoubleEndInterfacePublicClass CalculatorService
        Implements ICalculatorService
    
        PublicFunction Add(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDoubleImplements ICalculatorService.Add
            Return n1 + n2
    
        EndFunctionPublicFunction Subtract(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDoubleImplements ICalculatorService.Subtract
            Return n1 - n2
    
        EndFunctionEndClass
    
    [ServiceContract()]
    publicinterface ICalculatorService
    {
        [OperationContract]
        double Add(double n1, double n2);
        [OperationContract]
        double Subtract(double n1, double n2);
    }
    
    publicclass CalculatorService : ICalculatorService
    {
        publicdouble Add(double n1, double n2) { return n1 + n2; }
        publicdouble Subtract(double n1, double n2) { return n1 - n2; }
    }
    
  4. Legen Sie den WCF-Dienst auf einen bestimmten Anschluss auf Ihrem Webserver.

    Verwenden Sie beliebige Portnummer zwischen 10000 und 650000. In diesem Beispiel wird Port 50505 verwendet.

  5. Starten Sie den Web-Server.

    Wenn Sie WSDL (Web Services Description Language)-Ausgabe anzeigen und den Dienst auf Localhost ausführen möchten, wechseln Sie zu https://localhost:50505/CalculatorService/Service.svc?wsdl. Verwenden Sie die dieselbe Portnummer und Web-Projektnamen, den Sie angegeben, für den WCF-Dienst.

  6. Wenn Sie beabsichtigen, von einem Remotecomputer oder einem Gerät eine Verbindung mit dem Webserver herstellen, richten Sie ein virtuelles Verzeichnis auf das Verzeichnis, auf dem das Webprojekt enthält ein.

    Hinweis

    ASP.NET Development Server im Visual Studio reagiert nur auf Anforderungen von Ihrem lokalen Entwicklungscomputer.Wir empfehlen die Verwendung IIS-ein virtuelles Verzeichnis an.So können Sie eine Verbindung mit dem Webserver von einem Remotegerät her, solange der Server erreichbar ist.

  7. Vergewissern Sie sich, dass Sie von einem Desktopbrowser und einem Gerätebrowser auf das Verzeichnis zugreifen können.

So erstellen Sie den .NET Framework-client

  1. Während der Dienst ausgeführt wird, öffnen Sie eine Befehlszeile, und navigieren zu dem Verzeichnis, in dem sich WCF-Dienst befindet.

  2. Führen Sie über die Befehlszeile das WCF ServiceModel Desktop Dienstprogramm Tool (SvcUtil.exe), um einen WCF-Clientproxy zu generieren. Hier ist ein Beispiel des Befehlszeilenprogramms Aufrufs für SvcUtil in dem der Dienst für Localhost gehostet wird:

    svcutil.exe /language:c# https://localhost:50505/CalculatorService/Service.svc
    

    Das folgende Beispiel zeigt einen Clientproxy von SvcUtil, die auf einfachen Rechner Beispiel basiert generiert.

                                //------------------------------------------------------------------------------
                                // <auto-generated>
                                //     This code was generated by a tool.
                                //     Runtime Version:2.0.50727.42
                                //
                                //     Changes to this file may cause incorrect behavior and will be lost if
                                //     the code is regenerated.
                                // </auto-generated>
                                //------------------------------------------------------------------------------
    
    
    
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName="ICalculatorService")]
    publicinterface ICalculatorService
    {
    
        [System.ServiceModel.OperationContractAttribute(Action="https://fabrikam.com/ICalculatorService/Add", ReplyAction="https://fabrikam.com/ICalculatorService/AddResponse")]
        double Add(double n1, double n2);
    
        [System.ServiceModel.OperationContractAttribute(Action="https://fabrikam.com/ICalculatorService/Subtract", ReplyAction="https://fabrikam.com/ICalculatorService/SubtractResponse")]
        double Subtract(double n1, double n2);
    }
    
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    publicinterface ICalculatorServiceChannel : ICalculatorService, System.ServiceModel.IClientChannel
    {
    }
    
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    publicpartialclass CalculatorServiceClient : System.ServiceModel.ClientBase<ICalculatorService>, ICalculatorService
    {
    
        public CalculatorServiceClient()
        {
        }
    
        public CalculatorServiceClient(string endpointConfigurationName) : 
                base(endpointConfigurationName)
        {
        }
    
        public CalculatorServiceClient(string endpointConfigurationName, string remoteAddress) : 
                base(endpointConfigurationName, remoteAddress)
        {
        }
    
        public CalculatorServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(endpointConfigurationName, remoteAddress)
        {
        }
    
        public CalculatorServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(binding, remoteAddress)
        {
        }
    
        publicdouble Add(double n1, double n2)
        {
            returnbase.Channel.Add(n1, n2);
        }
    
        publicdouble Subtract(double n1, double n2)
        {
            returnbase.Channel.Subtract(n1, n2);
        }
    }
    
  3. Entfernen Sie nicht unterstützte Attribute und Elemente aus den generierten Proxy Clientcode, einschließlich der folgenden:

    • Alle System.ServiceModel Attribute.

    • Verweise auf die IClientChannel-Klasse.

    • Verweise auf <endpoint> Konfigurationsnamen.

    • Methodenimplementierungen, die Methoden der Schnittstelle ServiceContract auf dem internen Kanal aufrufen.

    Das folgende Beispiel zeigt den Code nach diesen Änderungen.

                                '------------------------------------------------------------------------------
                                ' <auto-generated>
                                '     This code was generated by a tool.
                                '     Runtime Version:2.0.50727.312
                                '
                                '     Changes to this file may cause incorrect behavior and will be lost if
                                '     the code is regenerated.
                                ' </auto-generated>
                                '------------------------------------------------------------------------------
                                Option Strict Off
    Option Explicit OnPublicInterface ICalculatorService
    
        Function Add(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDoubleFunction Subtract(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDoubleEndInterfacePartialPublicClass CalculatorServiceClient
        Inherits System.ServiceModel.ClientBase(Of ICalculatorService)
        Implements ICalculatorService
    
        ' Add a variable containing the endpoint address.PublicShared ServiceEndPoint AsNew System.ServiceModel.EndpointAddress("https://fabrikam.com/CalcService/CalculatorService/Service.svc")
    
        PublicSubNew(ByVal binding As System.ServiceModel.Channels.Binding, ByVal remoteAddress As System.ServiceModel.EndpointAddress)
            MyBase.New(binding, remoteAddress)
        EndSubPublicFunction Add(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDoubleImplements ICalculatorService.Add
            ReturnMyBase.Channel.Add(n1, n2)
        EndFunctionPublicFunction Subtract(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDoubleImplements ICalculatorService.Subtract
            ReturnMyBase.Channel.Subtract(n1, n2)
        EndFunctionEndClass
    
                                //------------------------------------------------------------------------------
                                // <auto-generated>
                                //     This code was generated by a tool.
                                //     Runtime Version:2.0.50727.42
                                //
                                //     Changes to this file may cause incorrect behavior and will be lost if
                                //     the code is regenerated.
                                // </auto-generated>
                                //------------------------------------------------------------------------------
                                public
                                interface ICalculatorService
    {
    
        double Add(double n1, double n2);
    
        double Subtract(double n1, double n2);
    }
    
    publicpartialclass CalculatorServiceClient : System.ServiceModel.ClientBase<ICalculatorService>, ICalculatorService
    {
    
        // Add a variable to specify the server address.publicstatic System.ServiceModel.EndpointAddress ServiceEndPoint = new System.ServiceModel.EndpointAddress("https://fabrikam.com/CalcService/CalculatorService/Service.svc");
    
        public CalculatorServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(binding, remoteAddress)
        {
        }
    
        publicdouble Add(double n1, double n2)
        {
            returnbase.Channel.Add(n1, n2);
        }
    
        publicdouble Subtract(double n1, double n2)
        {
            returnbase.Channel.Subtract(n1, n2);
        }
    }
    
  4. Erstellen Sie ein Clientprojekt.

  5. Fügen Sie der generierten Clientproxys zum Projekt hinzu.

  6. Im Code generierten Proxy ändern Sie den voll qualifizierten Verweis auf ClientBase<TChannel> für die benutzerdefinierte ClientBase-Klasse.

  7. Fügen Sie in den generierten Proxycode Methodenimplementierungen durch Aufrufen der in der Klasse benutzerdefinierte CallClientBase-Methode hinzu.

                                Public
                                Function Add(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDoubleImplements ICalculatorService.Add
        Return System.Convert.ToDouble(MyBase.Call("Add", "https://fabrikam.com/CalcService/ICalculatorService/Add", NewString() {"n1", "n2"}, NewObject() {n1, n2}, GetType(Double)))
    EndFunction
    
                                public
                                double Add(double n1, double n2)
    {
        return (double)base.Call("Add", "https://fabrikam.com/CalcService/ICalculatorService/Add", newstring[] { "n1", "n2" }, newobject[] { n1, n2 }, typeof(double));
    }
    
  8. Fügen Sie die Basisklasse für den Proxy zum Projekt hinzu. Diese Klasse wird mit der Bezeichnung ClientBase.

    Ändern Sie den Basisklasse Verweis des Proxies Client, auf die Implementierung von ClientBase.

    Hinweis

    In diesem Beispiel unterstützt die CustomBodyWriter -Klasse in ClientBase nur primitive Typen.Um nicht primitiven Typen zu unterstützen, müssen Sie OnWriteBodyContents Methode erweitern.Sie können z. B. ein benutzerdefiniertes Serialisierungsprogramm zum Serialisieren von Nachrichtendaten aufrufen.In diesem Fall würden Sie CodeAttribute im generierten Clientproxy Attribute übersetzen, die das XML-Serialisierungsprogramm verbrauchen kann.In diesem Szenario müssen Sie zunächst den folgenden Schalter beim Ausführen von SvcUtil hinzufügen: /serializer:xmlserializer http://Endpunkt.

    Der folgende Code zeigt ein Beispiel der ClientBase-Klasse.

                                Public
                                Class ClientBase(Of TChannel AsClass)
    
        Private requestChannel As IRequestChannel
        Private messageVersion As MessageVersion
    
    
        PublicSubNew(ByVal binding As System.ServiceModel.Channels.Binding, ByVal remoteAddress As System.ServiceModel.EndpointAddress)
            'this.remoteAddress = remoteAddress;Me.messageVersion = binding.MessageVersion
    
            Dim channelFactory As IChannelFactory(Of IRequestChannel)
            channelFactory = binding.BuildChannelFactory(Of IRequestChannel)(New BindingParameterCollection())
            channelFactory.Open()
            Me.requestChannel = channelFactory.CreateChannel(remoteAddress)
    
        EndSubPublicFunction [Call](ByVal op AsString, ByVal action AsString, ByVal varnames() AsString, ByVal varvals() AsObject, ByVal returntype As Type) AsObject
            requestChannel.Open(TimeSpan.MaxValue)
    
            Dim msg As Message = Message.CreateMessage(Me.messageVersion, action, New CustomBodyWriter(op, varnames, varvals, "<ns passed in from Proxy>"))
    
            Dim reply As Message = requestChannel.Request(msg, TimeSpan.MaxValue)
            Dim reader As XmlDictionaryReader = reply.GetReaderAtBodyContents()
            reader.ReadToFollowing(op + "Result")
            Return reader.ReadElementContentAs(returntype, Nothing)
    
        EndFunctionEndClassFriendClass CustomBodyWriter
        Inherits BodyWriter
        Private op AsStringPrivate varnames() AsStringPrivate varvals() AsObjectPrivate ns AsStringPublicSubNew(ByVal op AsString, ByVal varnames() AsString, ByVal varvals() AsObject, ByVal ns AsString)
            MyBase.New(True)
            Me.op = op
            Me.varnames = varnames
            Me.varvals = varvals
            Me.ns = ns
    
        EndSubProtectedOverridesSub OnWriteBodyContents(ByVal writer As XmlDictionaryWriter)
            writer.WriteStartElement(op, ns)
            Dim i AsIntegerFor i = 0 To varnames.Length
                writer.WriteElementString(varnames(i), varvals(i).ToString())
            Next i
            writer.WriteEndElement()
    
        EndSubEndClass
    
                                public
                                class ClientBase<TChannel>
        where TChannel : class
    {
        private IRequestChannel requestChannel;
        private MessageVersion messageVersion;
    
        public ClientBase(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress)
        {
            //this.remoteAddress = remoteAddress;this.messageVersion = binding.MessageVersion;
    
            IChannelFactory<IRequestChannel> channelFactory = binding.BuildChannelFactory<IRequestChannel>(
                new BindingParameterCollection());
            channelFactory.Open();
            this.requestChannel = channelFactory.CreateChannel(remoteAddress);
        }
    
        publicobject Call(string op, string action, string[] varnames, object[] varvals, Type returntype)
        {
            requestChannel.Open(TimeSpan.MaxValue);
    
            //Message msg =                     //Message.CreateMessage(MessageVersion.<FromBinding>,//      action,//      new CustomBodyWriter(op, varnames, varvals,               //"<ns passed in from Proxy>"));
    
            Message msg =                   
            Message.CreateMessage(this.messageVersion, action,
                  new CustomBodyWriter(op, varnames, varvals,               
            "<ns passed in from Proxy>"));
    
            Message reply = requestChannel.Request(msg, TimeSpan.MaxValue);
            XmlDictionaryReader reader = reply.GetReaderAtBodyContents();
            reader.ReadToFollowing(op + "Result");
            return reader.ReadElementContentAs(returntype, null);
        }
    
    }
    
    internalclass CustomBodyWriter : BodyWriter
    {
        privatestring op;
        privatestring[] varnames;
        privateobject[] varvals;
        privatestring ns;
    
        public CustomBodyWriter(string op, string[] varnames, object[] varvals, string ns)
            : base(true)
        {
            this.op = op;
            this.varnames = varnames;
            this.varvals = varvals;
            this.ns = ns;
        }
    
        protectedoverridevoid OnWriteBodyContents(XmlDictionaryWriter writer)
        {
            writer.WriteStartElement(op, ns);
            for (int i = 0; i < varnames.Length; i++)
                writer.WriteElementString(varnames[i], varvals[i].ToString());
            writer.WriteEndElement();
        }
    }
    
  9. Fügen Sie eine Klasse zu instanziieren und verwenden den Clientproxy.

    Das folgende Beispiel zeigt Code, der den Clientproxy aufruft.

                                Shared
                                Sub Main(ByVal args() AsString)
        Dim serverAddress AsString = CalculatorServiceClient.ServiceEndPoint.Uri.AbsoluteUri
        ' Using basic http connection. WS binding should be also available.Dim proxy As ICalculatorService = New CalculatorServiceClient(New BasicHttpBinding, New EndpointAddress(serverAddress))
        MessageBox.Show("Add 3 + 6...")
        MessageBox.Show(proxy.Add(3, 6).ToString)
        MessageBox.Show("Subtract 8 - 3...")
        MessageBox.Show(proxy.Subtract(8, 3).ToString)
    EndSub
    
                                static
                                void Main()
    {
        string serverAddress = CalculatorServiceClient.ServiceEndPoint.Uri.AbsoluteUri;
        // Using basic http connection. WS binding should be also available.
        ICalculatorService proxy = new CalculatorServiceClient(new BasicHttpBinding(), new EndpointAddress(serverAddress));
    
    
        MessageBox.Show("Add 3 + 6...");
        MessageBox.Show((proxy.Add(3, 6)).ToString());
        MessageBox.Show("Subtract 8 - 3...");        
        MessageBox.Show((proxy.Subtract(8, 3)).ToString());
    
    }
    
  10. Die Client-Anwendung erstellen und auf Ihrem Gerät bereitgestellt.

  11. Wenn WCF-Dienst ausgeführt wird und das Gerät mit dem Netzwerk verbunden ist, starten Sie die Clientanwendung auf dem Gerät.

Kompilieren des Codes

Der Quellcode für den WCF-Dienst sind Verweise auf die folgenden Namespaces erforderlich:

Der Quellcode für die ClientBase-Klasse sind Verweise auf die folgenden Namespaces erforderlich:

Der Quellcode für die Klasse, die Main-Methode in der Clientanwendung enthält, sind Verweise auf die folgenden Namespaces erforderlich:

Sicherheit

In diesem Beispiel implementiert keine WCF-Sicherheitsfunktionen. Weitere Informationen zu unterstützten Sicherheitsfeatures finden Sie unter In .NET Compact Framework Messaging.

Siehe auch

Konzepte

In .NET Compact Framework Messaging

Weitere Ressourcen

Windows Communication Foundation (WCF) Entwicklung und .NET Compact Framework