Especificación de una dirección de extremo
Toda comunicación con un servicio de Windows Communication Foundation (WCF) se produce a través de sus extremos. Cada ServiceEndpoint contiene un Address, un Bindingy un Contract. El contrato especifica qué operaciones están disponibles. El enlace especifica cómo comunicarse con el servicio y la dirección especifica dónde encontrar el servicio. Cada extremo debe tener una dirección única. La clase EndpointAddress representa la dirección de extremo, que contiene un Identificador uniforme de recursos (URI) que representa la dirección del servicio, una Identity, que representa la identidad de seguridad del servicio, y una colección de Headersopcional. Los encabezados opcionales proporcionan información más detallada de direccionamiento para identificar o interactuar con el extremo. Por ejemplo, los encabezados pueden indicar cómo procesar un mensaje entrante, dónde debería enviar el extremo un mensaje de respuesta o qué instancia de un servicio se va a usar para procesar un mensaje entrante de un usuario determinado cuando hay varias instancias disponibles.
Definición de una dirección del extremo
En WCF, una EndpointAddress modela una referencia del extremo (EPR), tal y como se define en la norma WS-Addressing.
El URI de la dirección de la mayoría de transportes tiene cuatro partes. Por ejemplo, este URI, "http://www.fabrikam.com: 322/mathservice .svc/secureEndpoint" tiene las cuatro partes siguientes:
Esquema: http:
Equipo: www.fabrikam.com
(Opcional) Puerto: 322
Ruta de acceso: /mathservice.svc/secureEndpoint
Parte del modelo EPR consiste en que cada referencia de extremo puede llevar algunos parámetros de referencia que agregan información de identificación adicional. En WCF, estos parámetros de referencia se modelan como instancias de la clase AddressHeader.
La dirección del extremo de un servicio puede especificarse de manera imperativa mediante código, o de manera declarativa mediante configuración. Normalmente, no resulta muy práctico definir los extremos en el código ya que los enlaces y las direcciones de un servicio implementado son, por lo general, diferentes de los utilizados durante el desarrollo del servicio. Generalmente, es más práctico definir extremos de servicio mediante la configuración en lugar del código. Mantener la información del enlace y el direccionamiento fuera del código permite cambiar los extremos sin tener que volver a compilar e implementar la aplicación. Si no se especifica ningún extremo en el código o en la configuración, el tiempo de ejecución agrega un extremo predeterminado en cada dirección base de cada contrato de servicio implementado por el servicio.
Hay dos maneras de especificar las direcciones del extremo de un servicio en WCF. Puede especificar una dirección absoluta para cada extremo asociado al servicio o puede proporcionar una dirección base para ServiceHost de un servicio y, a continuación, especificar una dirección para cada extremo asociado a este servicio que se define relativo a esta dirección base. Puede utilizar cada uno de estos procedimientos para especificar las direcciones de extremo de un servicio mediante configuración o código. Si no especifica una dirección relativa, el servicio utiliza la dirección base. También puede tener varias direcciones base para un servicio, pero en cada servicio se permite sólo una dirección base para cada transporte. Si tiene varios extremos, cada uno de los cuales está configurado con un enlace diferente, sus direcciones deben ser únicas. Los extremos que utilizan el mismo enlace pero contratos diferentes pueden utilizar la misma dirección.
Al hospedarse con IIS, no administra por sí mismo las instancias ServiceHost. La dirección base siempre es la dirección especificada en el archivo .svc para el servicio al hospedarse en IIS. De modo que siempre debe utilizar direcciones de extremo relativas para los extremos de servicio hospedados en IIS. Proporcionar una dirección de extremo completa puede conducir a errores en la implementación del servicio. Para obtener más información, vea Implementación de un servicio WFC hospedado en Internet Information Services.
Definición de direcciones de extremos mediante configuración
Para definir un extremo en un archivo de configuración, utilice el elemento <endpoint>.
<configuration>
<system.serviceModel>
<services>
<service name="UE.Samples.HelloService"
behaviorConfiguration="HelloServiceBehavior">
<endpoint address="/Address1"
binding="basicHttpBinding"
contract="UE.Samples.IHello"/>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="HelloServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Cuando se llama (es decir, cuando la aplicación de hospedaje intenta iniciar el servicio) al método Open, el sistema busca un elemento <service> con un atributo de nombre que especifica "UE.Samples.HelloService". Si se encuentra el elemento <service>, el sistema carga la clase especificada y crea los extremos utilizando las definiciones de extremo proporcionadas en el archivo de configuración. Este mecanismo le permite cargar e iniciar un servicio con dos líneas de código, mientras mantiene la información de enlace y dirección fuera de su código. La ventaja de este enfoque es que estas modificaciones se pueden realizar sin tener que volver a compilar o implementar la aplicación.
Los encabezados opcionales se declaran en <headers> element. Lo siguiente es un ejemplo de los elementos utilizados para especificar los extremos de un servicio en un archivo de configuración que distinga entre dos encabezados: Clientes "Gold" de http://tempuri1.org/ y clientes "Standard" de http://tempuri2.org/. El cliente que llama a este servicio debe tener el <headers> element adecuado en su archivo de configuración.
<configuration>
<system.serviceModel>
<services>
<service name="UE.Samples.HelloService"
behaviorConfiguration="HelloServiceBehavior">
<endpoint address="/Address1"
binding="basicHttpBinding"
contract="UE.Samples.IHello">
<headers>
<Member xmlns="http://tempuri1.org/">Gold</Member>
</headers>
</endpoint>
<endpoint address="/Address2"
binding="basicHttpBinding"
contract="UE.Samples.IHello">
<headers>
<Member xmlns="http://tempuri2.org/">Silver</Member>
</headers>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="HelloServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Los encabezados también se pueden definir como en mensajes individuales en lugar de todos los mensajes en un extremo (como se ha mostrado previamente). Ello se consigue utilizando OperationContextScope para crear un nuevo contexto en una aplicación de cliente para agregar un encabezado personalizado al mensaje saliente, tal y como se muestra en el ejemplo siguiente.
Dim wcfClient As New SampleServiceClient(New InstanceContext(Me))
Try
Using scope As New OperationContextScope(wcfClient.InnerChannel)
Dim header As MessageHeader = MessageHeader.CreateHeader("Service-Bound-CustomHeader", _
"http://Microsoft.WCF.Documentation", "Custom Happy Value.")
OperationContext.Current.OutgoingMessageHeaders.Add(header)
' Making calls.
Console.WriteLine("Enter the greeting to send: ")
Dim greeting As String = Console.ReadLine()
'Console.ReadLine();
header = MessageHeader.CreateHeader("Service-Bound-OneWayHeader", _
"http://Microsoft.WCF.Documentation", "Different Happy Value.")
OperationContext.Current.OutgoingMessageHeaders.Add(header)
' One-way
wcfClient.Push(greeting)
Me.wait.WaitOne()
' Done with service.
wcfClient.Close()
Console.WriteLine("Done!")
Console.ReadLine()
End Using
Catch timeProblem As TimeoutException
Console.WriteLine("The service operation timed out. " & timeProblem.Message)
Console.ReadLine()
wcfClient.Abort()
Catch commProblem As CommunicationException
Console.WriteLine("There was a communication problem. " & commProblem.Message)
Console.ReadLine()
wcfClient.Abort()
End Try
SampleServiceClient wcfClient = new SampleServiceClient(new InstanceContext(this));
try
{
using (OperationContextScope scope = new OperationContextScope(wcfClient.InnerChannel))
{
MessageHeader header
= MessageHeader.CreateHeader(
"Service-Bound-CustomHeader",
"http://Microsoft.WCF.Documentation",
"Custom Happy Value."
);
OperationContext.Current.OutgoingMessageHeaders.Add(header);
// Making calls.
Console.WriteLine("Enter the greeting to send: ");
string greeting = Console.ReadLine();
//Console.ReadLine();
header = MessageHeader.CreateHeader(
"Service-Bound-OneWayHeader",
"http://Microsoft.WCF.Documentation",
"Different Happy Value."
);
OperationContext.Current.OutgoingMessageHeaders.Add(header);
// One-way
wcfClient.Push(greeting);
this.wait.WaitOne();
// Done with service.
wcfClient.Close();
Console.WriteLine("Done!");
Console.ReadLine();
}
}
catch (TimeoutException timeProblem)
{
Console.WriteLine("The service operation timed out. " + timeProblem.Message);
Console.ReadLine();
wcfClient.Abort();
}
catch (CommunicationException commProblem)
{
Console.WriteLine("There was a communication problem. " + commProblem.Message);
Console.ReadLine();
wcfClient.Abort();
}
Dirección del extremo en metadatos
Una dirección de extremo se representa en el Lenguaje de descripción de servicios web (WSDL) como un elemento EndpointReference (EPR) de WS-Addressing dentro del elemento wsdl:port del extremo correspondiente. El EPR contiene la dirección del extremo, así como todas las propiedades de la dirección. Observe que la EPR dentro de wsdl:port reemplaza a soap:Address, como se observa en el siguiente ejemplo.
Definición de direcciones del extremo mediante código
Una dirección de extremo se puede crear mediante código con la clase EndpointAddress. El URI especificado para la dirección del extremo puede ser una ruta de acceso completa o una ruta de acceso relativa a la dirección base del servicio. En el siguiente ejemplo observaremos cómo crear una nueva instancia de la clase EndpointAddress y agregarla a la instancia ServiceHost que hospeda el servicio.
En el siguiente ejemplo se muestra cómo se especifica una dirección de extremo completa mediante código.
Uri baseAddress = new Uri("https://localhost:8000/HelloService");
string address = "https://localhost:8000/HelloService/MyService";
using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), address);
serviceHost.Open();
Console.WriteLine("Press <enter> to terminate service");
Console.ReadLine();
serviceHost.Close();
}
El ejemplo siguiente muestra cómo agregar una dirección relativa ("MyService") a la dirección base del host de servicio.
Uri baseAddress = new Uri("https://localhost:8000/HelloService");
using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), "MyService");
serviceHost.Open();
Console.WriteLine("Press <enter> to terminate service");
Console.ReadLine();
serviceHost.Close();
}
Nota: |
---|
Las propiedades de ServiceDescription en la aplicación de servicio no se deben modificar después del método OnOpening en ServiceHostBase. Algunos miembros, como la propiedad Credentials y los métodos AddServiceEndpoint en ServiceHostBase y ServiceHost, inician una excepción si se modifican después de ese punto. Otros permiten modificarlos, pero el resultado no está definido. De manera similar, en el cliente no se deben modificar los valores ServiceEndpoint después de llamar a OnOpening en ChannelFactory. La propiedad Credentials inicia una excepción si se modifica pasado ese punto. Los otros valores de descripción del cliente pueden modificarse sin error, pero el resultado no está definido. Tanto si es para el servicio como para el cliente, se recomienda modificar la descripción antes de llamar a Open. |
Usar extremos predeterminados
Si no se especifica ningún extremo en el código ni en la configuración, el tiempo de ejecución proporciona extremos predeterminados, agregando uno en cada dirección base de cada contrato de servicio implementado por el servicio. La dirección base se puede especificar en el código o en la configuración, y los extremos predeterminados se agregan al llamar al método Open en el objeto ServiceHost.
Si se proporcionan extremos de forma explícita, es posible agregar extremos predeterminados llamando a AddDefaultEndpoints en el objeto ServiceHost antes de llamar a Open. Para obtener más información sobre extremos, enlaces y comportamientos predeterminados, vea Configuración simplificada y Configuración simplificada de los servicios de WCF.
Vea también
Referencia
Conceptos
Identidad del servicio y autenticación
Información general acerca de la creación de puntos finales