Cómo: Obtener acceso a los servicios WCF con contratos unidireccionales y de solicitud-respuesta
Los procedimientos siguientes describen cómo tener acceso a un servicio Windows Communication Foundation (WCF) que define un contrato unidireccional y un contrato de solicitud-respuesta y no utiliza el modelo de comunicación dúplex.
Para definir el servicio
Declare el contrato de servicio. Las operaciones que son unidireccionales deben tener
IsOneWay
establecido entrue
dentro de OperationContractAttribute. El código siguiente declara el contratoIOneWayCalculator
que tiene operaciones unidireccionales paraAdd
,Subtract
,Multiply
yDivide
. También define una operación de respuesta de solicitud denominadaSayHello
.[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); }
Implemente el contrato de servicios. En el código siguiente se implementa la interfaz
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; } }
Hospede el servicio en una aplicación de consola. En el código siguiente se muestra cómo hospedar el servicio.
// 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(); } }
Para obtener acceso al servicio
Ejecute la Herramienta de utilidad de metadatos de ServiceModel (Svcutil.exe) utilizando la dirección de extremo de intercambio de metadatos, con el fin de crear la clase de cliente para el servicio, mediante la línea de comandos siguiente:
Svcutil https://localhost:8000/Service
. La Herramienta de utilidad de metadatos de ServiceModel (Svcutil.exe) genera un conjunto de interfaces y clases, como se muestra en el código de ejemplo siguiente.[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); } }
Observe en la interfaz
IOneWayCalculator
que las operaciones de servicio unidireccionales tienen el atributo IsOneWay establecido en true y que la operación de servicio de solicitud-respuesta tiene el atributo establecido en el valor predeterminado, false. Observe también la claseOneWayCalculatorClient
. Ésta es la clase que se utilizará para llamar al servicio.Cree el objeto de cliente.
// Create a client WSHttpBinding binding = new WSHttpBinding(); EndpointAddress epAddress = new EndpointAddress("https://localhost:8000/servicemodelsamples/service"); OneWayCalculatorClient client = new OneWayCalculatorClient(binding, epAddress);
Operaciones de servicio de llamada.
// 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);
Cierre el cliente para cerrar las conexiones y limpiar los recursos.
//Closing the client gracefully closes the connection and cleans up resources client.Close();
Ejemplo
A continuación, se muestra la lista completa del código que se emplea en este tema.
// 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();
}
}
}