Поделиться через


Практическое руководство. Доступ к службам WCF с односторонним контрактом и контрактом типа «запрос-ответ»

В следующих процедурах описан способ доступа к службе Windows Communication Foundation (WCF), определяющей односторонний контракт и контракт типа запрос-ответ и не использующей дуплексный обмен данными.

Определение службы

  1. Объявите контракт службы. Для операций, которые требуется сделать односторонними, необходимо назначить для IsOneWay значение true в атрибуте OperationContractAttribute. В следующем коде объявляется контракт IOneWayCalculator, имеющий односторонние операции для Add, Subtract, Multiply и Divide. В нем также определяется операция ответа на запрос, называемая SayHello.

        [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
        public interface IOneWayCalculator
        {
            [OperationContract(IsOneWay = true)]
            void Add(double n1, double n2);
            [OperationContract(IsOneWay = true)]
            void Subtract(double n1, double n2);
            [OperationContract(IsOneWay = true)]
            void Multiply(double n1, double n2);
            [OperationContract(IsOneWay = true)]
            void Divide(double n1, double n2);
            [OperationContract]
            string SayHello(string name);
        }
    
  2. Реализуйте контракт службы. В следующем коде реализуется интерфейс IOnewayCalculator.

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)]
    public class CalculatorService : IOneWayCalculator
    {
        public void Add(double n1, double n2)
        {
           double result = n1 + n2;
           Console.WriteLine("Add({0},{1}) = {2} ", n1, n2, result);
        }
    
        public void Subtract(double n1, double n2)
        {
           double result = n1 - n2;
           Console.WriteLine("Subtract({0},{1}) = {2}", n1, n2, result);
        }
    
        public void Multiply(double n1, double n2)
        {
            double result = n1 * n2;
            Console.WriteLine("Multiply({0},{1}) = {2}", n1, n2, result);
        }
    
        public void Divide(double n1, double n2)
        {
            double result = n1 / n2;
            Console.WriteLine("Divide({0},{1}) = {2}", n1, n2, result);
        }
    
        public string SayHello(string name)
        {
            Console.WriteLine("SayHello({0})", name);
            return "Hello " + name;
        }
    }
    
  3. Разместите службу в консольном приложении. В следующем примере кода показано, как это сделать.

    // Host the service within this EXE console application.
    public static void Main()
    {
       // Define the base address for the service.
       Uri baseAddress = new Uri("https://localhost:8000/servicemodelsamples/service");
    
       // Create a ServiceHost for the CalculatorService type and provide the base address.
       using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService), baseAddress))
       {
            // Add an endpoint using the IOneWayCalculator contract and the WSHttpBinding
            serviceHost.AddServiceEndpoint(typeof(IOneWayCalculator), new WSHttpBinding(), "");
    
          // Turn on the metadata behavior, this allows svcutil to get metadata for the service.
          ServiceMetadataBehavior smb = (ServiceMetadataBehavior) serviceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
          if (smb == null)
          {
                smb = new ServiceMetadataBehavior();
                smb.HttpGetEnabled = true;
                serviceHost.Description.Behaviors.Add(smb);
          }
    
          // Open the ServiceHostBase to create listeners and start listening for messages.
          serviceHost.Open();
    
          // The service can now be accessed.
          Console.WriteLine("The service is ready.");
          Console.WriteLine("Press <ENTER> to terminate service.");
          Console.WriteLine();
          Console.ReadLine();
        }
    }
    

Доступ к службе

  1. Выполните программу Служебное средство ServiceModel Metadata Utility Tool (Svcutil.exe), используя адрес конечной точки для обмена метаданными, чтобы создать класс клиента для службы. Для этого воспользуйтесь следующей командой для командной строки: Svcutil https://localhost:8000/Service. Программа Служебное средство ServiceModel Metadata Utility Tool (Svcutil.exe) создает набор интерфейсов и классов, как показано в следующем примере кода.

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(Namespace="http://Microsoft.ServiceModel.Samples", ConfigurationName="IOneWayCalculator")]
    public interface IOneWayCalculator
    {
    
        [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="http://Microsoft.ServiceModel.Samples/IOneWayCalculator/Add")]
        void Add(double n1, double n2);
    
        [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="http://Microsoft.ServiceModel.Samples/IOneWayCalculator/Subtract")]
        void Subtract(double n1, double n2);
    
        [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="http://Microsoft.ServiceModel.Samples/IOneWayCalculator/Multiply")]
        void Multiply(double n1, double n2);
    
        [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="http://Microsoft.ServiceModel.Samples/IOneWayCalculator/Divide")]
        void Divide(double n1, double n2);
    
        [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/IOneWayCalculator/SayHello", ReplyAction="http://Microsoft.ServiceModel.Samples/IOneWayCalculator/SayHelloResponse")]
        string SayHello(string name);
    }
    
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    public interface IOneWayCalculatorChannel : IOneWayCalculator, System.ServiceModel.IClientChannel
    {
    }
    
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    public partial class OneWayCalculatorClient : System.ServiceModel.ClientBase<IOneWayCalculator>, IOneWayCalculator
    {
    
        public OneWayCalculatorClient()
        {
        }
    
        public OneWayCalculatorClient(string endpointConfigurationName) : 
                base(endpointConfigurationName)
        {
        }
    
        public OneWayCalculatorClient(string endpointConfigurationName, string remoteAddress) : 
                base(endpointConfigurationName, remoteAddress)
        {
        }
    
        public OneWayCalculatorClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(endpointConfigurationName, remoteAddress)
        {
        }
    
        public OneWayCalculatorClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(binding, remoteAddress)
        {
        }
    
        public void Add(double n1, double n2)
        {
            base.Channel.Add(n1, n2);
        }
    
        public void Subtract(double n1, double n2)
        {
            base.Channel.Subtract(n1, n2);
        }
    
        public void Multiply(double n1, double n2)
        {
            base.Channel.Multiply(n1, n2);
        }
    
        public void Divide(double n1, double n2)
        {
            base.Channel.Divide(n1, n2);
        }
    
        public string SayHello(string name)
        {
            return base.Channel.SayHello(name);
        }
    }
    

    Обратите внимание, что в интерфейсе IOneWayCalculator односторонним операциям службы задано значение true для атрибута IsOneWay, а операции запроса-ответа службы для этого атрибута задано значение по умолчанию: false. Также обратите внимание на класс OneWayCalculatorClient. Он используется для вызова службы.

  2. Создайте клиентский объект.

    // Create a client
    WSHttpBinding binding = new WSHttpBinding();
    EndpointAddress epAddress = new EndpointAddress("https://localhost:8000/servicemodelsamples/service");
    OneWayCalculatorClient client = new OneWayCalculatorClient(binding, epAddress);
    
  3. Вызовите операции службы.

    // Call the Add service operation.
    double value1 = 100.00D;
    double value2 = 15.99D;
    client.Add(value1, value2);
    Console.WriteLine("Add({0},{1})", value1, value2);
    
    // Call the Subtract service operation.
    value1 = 145.00D;
    value2 = 76.54D;
    client.Subtract(value1, value2);
    Console.WriteLine("Subtract({0},{1})", value1, value2);
    
    // Call the Multiply service operation.
    value1 = 9.00D;
    value2 = 81.25D;
    client.Multiply(value1, value2);
    Console.WriteLine("Multiply({0},{1})", value1, value2);
    
    // Call the Divide service operation.
    value1 = 22.00D;
    value2 = 7.00D;
    client.Divide(value1, value2);
    Console.WriteLine("Divide({0},{1})", value1, value2);
    
    // Call the SayHello service operation
    string name = "World";
    string response = client.SayHello(name);
    Console.WriteLine("SayHello([0])", name);
    Console.WriteLine("SayHello() returned: " + response);
    
  4. Закройте клиент, чтобы закрыть соединения и очистить ресурсы.

    //Closing the client gracefully closes the connection and cleans up resources
    client.Close();
    

Пример

Код, фрагменты которого представлены в данном разделе, полностью приведен ниже.

// Service.cs
using System;
using System.Configuration;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace Microsoft.ServiceModel.Samples
{
    // Define a service contract. 
    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
    public interface IOneWayCalculator
    {
        [OperationContract(IsOneWay = true)]
        void Add(double n1, double n2);
        [OperationContract(IsOneWay = true)]
        void Subtract(double n1, double n2);
        [OperationContract(IsOneWay = true)]
        void Multiply(double n1, double n2);
        [OperationContract(IsOneWay = true)]
        void Divide(double n1, double n2);
        [OperationContract]
        string SayHello(string name);
    }
   
    // Service class which implements the service contract.
    // Added code to write output to the console window
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)]
    public class CalculatorService : IOneWayCalculator
    {
        public void Add(double n1, double n2)
        {
            double result = n1 + n2;
            Console.WriteLine("Add({0},{1}) = {2} ", n1, n2, result);
        }

        public void Subtract(double n1, double n2)
        {
            double result = n1 - n2;
            Console.WriteLine("Subtract({0},{1}) = {2}", n1, n2, result);
        }

        public void Multiply(double n1, double n2)
        {
            double result = n1 * n2;
            Console.WriteLine("Multiply({0},{1}) = {2}", n1, n2, result);
        }

        public void Divide(double n1, double n2)
        {
            double result = n1 / n2;
            Console.WriteLine("Divide({0},{1}) = {2}", n1, n2, result);
        }

        public string SayHello(string name)
        {
            Console.WriteLine("SayHello({0})", name);
            return "Hello " + name;
        }



        // Host the service within this EXE console application.
        public static void Main()
        {
            // Define the base address for the service.
            Uri baseAddress = new Uri("https://localhost:8000/servicemodelsamples/service");

            // Create a ServiceHost for the CalculatorService type and provide the base address.
            using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService), baseAddress))
            {
                // Add an endpoint using the IOneWayCalculator contract and the WSHttpBinding
                serviceHost.AddServiceEndpoint(typeof(IOneWayCalculator), new WSHttpBinding(), "");

                // Turn on the metadata behavior, this allows svcutil to get metadata for the service.
                ServiceMetadataBehavior smb = (ServiceMetadataBehavior) serviceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
                if (smb == null)
                {
                    smb = new ServiceMetadataBehavior();
                    smb.HttpGetEnabled = true;
                    serviceHost.Description.Behaviors.Add(smb);
                }

                // Open the ServiceHostBase to create listeners and start listening for messages.
                serviceHost.Open();

                // The service can now be accessed.
                Console.WriteLine("The service is ready.");
                Console.WriteLine("Press <ENTER> to terminate service.");
                Console.WriteLine();
                Console.ReadLine();
            }
        }
    }
}

// client.cs
using System;
using System.ServiceModel;

namespace Microsoft.ServiceModel.Samples
{
    //The service contract is defined in generatedClient.cs, generated from the service by the svcutil tool.

    //Client implementation code.
    class Client
    {
        static void Main()
        {
            // Create a client
            WSHttpBinding binding = new WSHttpBinding();
            EndpointAddress epAddress = new EndpointAddress("https://localhost:8000/servicemodelsamples/service");
            OneWayCalculatorClient client = new OneWayCalculatorClient(binding, epAddress);

            // Call the Add service operation.
            double value1 = 100.00D;
            double value2 = 15.99D;
            client.Add(value1, value2);
            Console.WriteLine("Add({0},{1})", value1, value2);

            // Call the Subtract service operation.
            value1 = 145.00D;
            value2 = 76.54D;
            client.Subtract(value1, value2);
            Console.WriteLine("Subtract({0},{1})", value1, value2);

            // Call the Multiply service operation.
            value1 = 9.00D;
            value2 = 81.25D;
            client.Multiply(value1, value2);
            Console.WriteLine("Multiply({0},{1})", value1, value2);

            // Call the Divide service operation.
            value1 = 22.00D;
            value2 = 7.00D;
            client.Divide(value1, value2);
            Console.WriteLine("Divide({0},{1})", value1, value2);

            // Call the SayHello service operation
            string name = "World";
            string response = client.SayHello(name);
            Console.WriteLine("SayHello([0])", name);
            Console.WriteLine("SayHello() returned: " + response);
            //Closing the client gracefully closes the connection and cleans up resources
            client.Close();


        }
    }
}

См. также

Основные понятия

One-Way Services