Compartir a través de


Comparación de servicios web de ASP.NET con WCF basado en el desarrollo

Windows Communication Foundation (WCF) tiene una opción de modo de compatibilidad ASP.NET para permitir que las aplicaciones WCF se programen y configuren como ASP.NET servicios web e imitan su comportamiento. En las secciones siguientes se comparan ASP.NET servicios web y WCF en función de lo necesario para desarrollar aplicaciones mediante ambas tecnologías.

Representación de datos

El desarrollo de un servicio web con ASP.NET normalmente comienza con la definición de cualquier tipo de datos complejo que use el servicio. ASP.NET se basa en el XmlSerializer para traducir los datos representados por tipos de .NET Framework a XML para la transmisión hacia o desde un servicio y para traducir los datos recibidos como XML en objetos de .NET Framework. La definición de los tipos de datos complejos que un servicio ASP.NET está destinado a utilizar requiere la definición de clases de .NET Framework que XmlSerializer pueda serializar a y desde XML. Estas clases se pueden escribir manualmente o generarse a partir de definiciones de los tipos del esquema XML mediante la utilidad de compatibilidad de esquemas XML de línea de comandos/tipos de datos, xsd.exe.

La siguiente lista muestra problemas clave que deben tenerse en cuenta al definir las clases de .NET Framework que XmlSerializer puede serializar a y desde XML:

  • Solo los campos y propiedades públicos de los objetos de .NET Framework se traducen en XML.

  • Las instancias de clases de colección solo se pueden serializar en XML si las clases implementan la IEnumerable interfaz o ICollection .

  • Las clases que implementan la IDictionary interfaz, como Hashtable, no se pueden serializar en XML.

  • La gran cantidad de tipos de atributo existente en el espacio de nombres System.Xml.Serialization, puede agregarse a una clase de .NET Framework y sus miembros para controlar la representación de las instancias de la clase en XML.

Normalmente, el desarrollo de aplicaciones WCF también comienza con la definición de tipos complejos. WCF se puede configurar para utilizar los mismos tipos de .NET Framework que los servicios web ASP.NET.

WCFDataContractAttribute y DataMemberAttribute se pueden agregar a tipos de .NET Framework para indicar que las instancias del tipo se van a serializar en XML y qué campos o propiedades concretos del tipo se van a serializar, como se muestra en el código de ejemplo siguiente.

//Example One:
[DataContract]
public class LineItem
{
    [DataMember]
    public string ItemNumber;
    [DataMember]
    public decimal Quantity;
    [DataMember]
    public decimal UnitPrice;
}

//Example Two:
public class LineItem
{
    [DataMember]
    private string itemNumber;
    [DataMember]
    private decimal quantity;
    [DataMember]
    private decimal unitPrice;

    public string ItemNumber
    {
      get
      {
          return this.itemNumber;
      }

      set
      {
          this.itemNumber = value;
      }
    }

    public decimal Quantity
    {
        get
        {
            return this.quantity;
        }

        set
        {
            this.quantity = value;
        }
    }

    public decimal UnitPrice
    {
      get
      {
          return this.unitPrice;
      }

      set
      {
          this.unitPrice = value;
      }
    }
}

//Example Three:
public class LineItem
{
     private string itemNumber;
     private decimal quantity;
     private decimal unitPrice;

     [DataMember]
     public string ItemNumber
     {
       get
       {
          return this.itemNumber;
       }

       set
       {
           this.itemNumber = value;
       }
     }

     [DataMember]
     public decimal Quantity
     {
          get
          {
              return this.quantity;
          }

          set
          {
             this.quantity = value;
          }
     }

     [DataMember]
     public decimal UnitPrice
     {
          get
          {
              return this.unitPrice;
          }

          set
          {
              this.unitPrice = value;
          }
     }
}

DataContractAttribute indica que se van a serializar cero o más de los campos o propiedades de un tipo, mientras DataMemberAttribute que indica que se va a serializar un campo o propiedad determinado. DataContractAttribute se puede aplicar a una clase o estructura. DataMemberAttribute se puede aplicar a un campo o una propiedad, y los campos y propiedades a los que se aplica el atributo pueden ser públicos o privados. Las instancias de tipos a los que se ha aplicado DataContractAttribute se conocen como contratos de datos en WCF. Se serializan en XML mediante DataContractSerializer.

A continuación se muestra una lista de las diferencias importantes entre usar DataContractSerializer y usar XmlSerializer, y los distintos atributos del espacio de nombres System.Xml.Serialization.

  • Los XmlSerializer atributos y del System.Xml.Serialization espacio de nombres están diseñados para permitirle asignar tipos de .NET Framework a cualquier tipo válido definido en el esquema XML, por lo que proporcionan un control muy preciso sobre cómo se representa un tipo en XML. DataContractSerializer, DataContractAttribute y DataMemberAttribute proporcionan muy poco control sobre cómo se representa un tipo en XML. Solo puede especificar los espacios de nombres y los identificadores utilizados para representar el tipo y sus campos o propiedades en el XML, así como la secuencia en que aparecen estos campos y propiedades.

    [DataContract(
    Namespace="urn:Contoso:2006:January:29",
    Name="LineItem")]
    public class LineItem
    {
          [DataMember(Name="ItemNumber",IsRequired=true,Order=0)]
          public string itemNumber;
          [DataMember(Name="Quantity",IsRequired=false,Order = 1)]
          public decimal quantity;
          [DataMember(Name="Price",IsRequired=false,Order = 2)]
          public decimal unitPrice;
    }
    

    Todo lo demás sobre la estructura del XML usado para representar el tipo de .NET viene determinado por .DataContractSerializer

  • Al no permitir mucho control sobre cómo se representa un tipo en XML, el proceso de serialización se vuelve muy predecible para el DataContractSerializer, y, por lo tanto, más fácil de optimizar. Una ventaja práctica del diseño de DataContractSerializer es un mejor rendimiento, aproximadamente diez por ciento mejor rendimiento.

  • Los atributos que se usan con XmlSerializer no indican qué campos o propiedades del tipo se serializan en XML, mientras que DataMemberAttribute para su uso con DataContractSerializer muestra explícitamente qué campos o propiedades se serializan. Por lo tanto, los contratos de datos son contratos explícitos sobre la estructura de los datos que una aplicación va a enviar y recibir.

  • XmlSerializer solo puede traducir los miembros públicos de un objeto .NET a XML, DataContractSerializer puede traducir los miembros de los objetos a XML independientemente de los modificadores de acceso de esos miembros.

  • Como consecuencia de poder serializar los miembros no públicos de tipos en XML, el DataContractSerializer tiene menos restricciones en la variedad de tipos de .NET que se pueden serializar en XML. En concreto, puede traducirse en tipos XML como Hashtable que implementen la IDictionary interfaz. DataContractSerializer Es mucho más probable que pueda serializar las instancias de cualquier tipo de .NET preexistente en XML sin tener que modificar la definición del tipo o desarrollar un contenedor para él.

  • Otra consecuencia de que DataContractSerializer pueda acceder a los miembros no públicos de un tipo es que requiere plena confianza, mientras que XmlSerializer no lo hace. El permiso de acceso al código de plena confianza proporciona acceso completo a todos los recursos de un equipo al que se puede acceder mediante las credenciales en las que se ejecuta el código. Esta opción debe usarse con cuidado, ya que el código de plena confianza accede a todos los recursos de la máquina.

  • DataContractSerializer incorpora cierta compatibilidad con el control de versiones:

    • DataMemberAttribute posee una propiedad IsRequired a la puede asignarse un valor de falso para los miembros que se agregan a las nuevas versiones de un contrato de datos que no se encontraban en versiones anteriores, con lo que las aplicaciones con la versión más reciente del contrato pueden procesar las versiones anteriores.

    • Al hacer que un contrato de datos implemente la IExtensibleDataObject interfaz, puede permitir que DataContractSerializer pase miembros definidos en versiones más recientes de un contrato de datos a través de aplicaciones con versiones anteriores del contrato.

A pesar de todas las diferencias, el XML en el que serializa XmlSerializer un tipo de forma predeterminada es semánticamente idéntico al XML en el que serializa DataContractSerializer un tipo, siempre que se defina explícitamente el espacio de nombres para el XML. La siguiente clase, que tiene atributos para su uso con ambos serializadores, se traduce en XML semánticamente idéntico tanto por XmlSerializer como por DataContractAttribute.

[Serializable]
[XmlRoot(Namespace="urn:Contoso:2006:January:29")]
[DataContract(Namespace="urn:Contoso:2006:January:29")]
public class LineItem
{
     [DataMember]
     public string ItemNumber;
     [DataMember]
     public decimal Quantity;
     [DataMember]
     public decimal UnitPrice;
}

El kit de desarrollo de software (SDK) de Windows incluye una herramienta de línea de comandos denominada ServiceModel Metadata Utility Tool (Svcutil.exe). Al igual que la herramienta de xsd.exe que se usa con ASP.NET servicios web, Svcutil.exe puede generar definiciones de tipos de datos de .NET a partir del esquema XML. Los tipos son contratos de datos si DataContractSerializer puede emitir XML en el formato definido por el esquema XML; de lo contrario, están diseñados para la serialización mediante XmlSerializer. Svcutil.exe también puede generar un esquema XML a partir de contratos de datos mediante su dataContractOnly conmutador.

Nota:

Aunque los servicios web de ASP.NET usan el modo de compatibilidad de XmlSerializer, y el modo de compatibilidad en ASP.NET de WCF hace que los servicios WCF imiten el comportamiento de los servicios web de ASP.NET, la opción de compatibilidad de ASP.NET no restringe el uso de XmlSerializer. Todavía se puede usar DataContractSerializer con los servicios que se ejecutan en el modo de compatibilidad de ASP.NET.

Desarrollo de servicios

Para desarrollar un servicio mediante ASP.NET, es habitual agregar el WebService atributo a una clase y WebMethodAttribute a cualquiera de los métodos de esa clase que van a ser operaciones del servicio:

[WebService]
public class Service : T:System.Web.Services.WebService
{
    [WebMethod]
    public string Echo(string input)
    {
       return input;
    }
}

ASP.NET 2.0 introdujo la opción de agregar el atributo WebService y WebMethodAttribute a una interfaz en lugar de a una clase y escribir una clase para implementar la interfaz:

[WebService]
public interface IEcho
{
    [WebMethod]
    string Echo(string input);
}

public class Service : IEcho
{

   public string Echo(string input)
   {
        return input;
    }
}

El uso de esta opción es preferible, ya que la interfaz con el WebService atributo constituye un contrato para las operaciones realizadas por el servicio que se pueden reutilizar con varias clases que podrían implementar ese mismo contrato de maneras diferentes.

Un servicio WCF se proporciona definiendo uno o varios puntos de conexión WCF. Un punto de conexión se define mediante una dirección, un enlace y un contrato de servicio. La dirección define dónde se encuentra el servicio. La vinculación especifica cómo comunicarse con el servicio. El contrato de servicio define las operaciones que puede realizar el servicio.

Normalmente, el contrato de servicio se define primero agregando ServiceContractAttribute y OperationContractAttribute a una interfaz:

[ServiceContract]
public interface IEcho
{
     [OperationContract]
     string Echo(string input);
}

ServiceContractAttribute especifica que la interfaz define un contrato de servicio WCF e OperationContractAttribute indica cuáles, si los hay, de los métodos de la interfaz definen las operaciones del contrato de servicio.

Una vez definido un contrato de servicio, se implementa en una clase, haciendo que la clase implemente la interfaz mediante la cual se define el contrato de servicio:

public class Service : IEcho
{
    public string Echo(string input)
    {
       return input;
    }
}

Una clase que implementa un contrato de servicio se conoce como un tipo de servicio en WCF.

El siguiente paso consiste en asociar una dirección y un enlace con un tipo de servicio. Normalmente, esto se realiza en un archivo de configuración, ya sea editando el archivo directamente o mediante un editor de configuración proporcionado con WCF. Este es un ejemplo de un archivo de configuración.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
     <system.serviceModel>
      <services>
      <service name="Service ">
       <endpoint
        address="EchoService"
        binding="basicHttpBinding"
        contract="IEchoService "/>
      </service>
      </services>
     </system.serviceModel>
</configuration>

El enlace especifica el conjunto de protocolos para comunicarse con la aplicación. En la tabla siguiente se enumeran los enlaces proporcionados por el sistema que representan opciones comunes.

Nombre Propósito
BasicHttpBinding Interoperabilidad con servicios web y clientes que admiten la WS-BasicProfile 1.1 y el perfil de seguridad básico 1.0.
WSHttpBinding Interoperabilidad con servicios web y clientes que admiten los protocolos WS-* a través de HTTP.
WSDualHttpBinding Comunicación HTTP dúplex, por la que el receptor de un mensaje inicial no responde directamente al remitente inicial, pero puede transmitir cualquier número de respuestas durante un período de tiempo mediante HTTP de conformidad con los protocolos WS-*.
WSFederationBinding La comunicación HTTP, en la que el acceso a los recursos de un servicio se puede controlar en función de las credenciales emitidas por un proveedor de credenciales identificado explícitamente.
NetTcpBinding Comunicación segura, confiable y de alto rendimiento entre entidades de software WCF a través de una red.
NetNamedPipeBinding Comunicación segura, confiable y de alto rendimiento entre entidades de software WCF en la misma máquina.
NetMsmqBinding Comunicación entre entidades de software WCF mediante MSMQ.
MsmqIntegrationBinding Comunicación entre una entidad de software WCF y otra entidad de software mediante MSMQ.
NetPeerTcpBinding Comunicación entre las entidades de software de WCF utilizando la conexión de red punto a punto de Windows.

El enlace proporcionado por el sistema, BasicHttpBinding, incorpora el conjunto de protocolos admitidos por ASP.NET servicios web.

Los enlaces personalizados para aplicaciones WCF se definen fácilmente como colecciones de las clases de elemento de enlace que WCF usa para implementar protocolos individuales. Los nuevos elementos de enlace se pueden escribir para representar protocolos adicionales.

El comportamiento interno de los tipos de servicio se puede ajustar mediante las propiedades de una familia de clases denominadas comportamientos. Aquí, la ServiceBehaviorAttribute clase se usa para especificar que el tipo de servicio debe ser multiproceso.

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
public class DerivativesCalculatorServiceType: IDerivativesCalculator

Algunos comportamientos, como ServiceBehaviorAttribute, son atributos. Otros, los que incluyen propiedades que los administradores desean establecer, se pueden modificar en la configuración de una aplicación.

En los tipos de servicio de programación, se utiliza frecuentemente la clase OperationContext. Su propiedad estática Current proporciona acceso a información sobre el contexto en el que se ejecuta una operación. OperationContext es similar a las HttpContext clases y ContextUtil .

Alojamiento

Los servicios web de ASP.NET se compilan en una biblioteca de clases. Se proporciona un archivo denominado archivo de servicio que tiene la extensión .asmx y contiene una @ WebService directiva que identifica la clase que contiene el código para el servicio y el ensamblado en el que se encuentra.

<%@ WebService Language="C#" Class="Service,ServiceAssembly" %>

El archivo de servicio se copia en una raíz de aplicación de ASP.NET en Internet Information Services (IIS) y el ensamblado se copia en el subdirectorio \bin de esa raíz de aplicación. A continuación, se puede acceder a la aplicación mediante el localizador uniforme de recursos (URL) del archivo de servicio en la raíz de la aplicación.

Los servicios WCF se pueden hospedar fácilmente en IIS 5.1 o 6.0, el servicio de activación de procesos de Windows (WAS) que se proporciona como parte de IIS 7.0 y dentro de cualquier aplicación .NET. Para hospedar un servicio en IIS 5.1 o 6.0, el servicio debe usar HTTP como protocolo de transporte de comunicaciones.

Para hospedar un servicio dentro de IIS 5.1, 6.0 o WAS, siga estos pasos:

  1. Compile el tipo de servicio en un ensamblado de biblioteca de clases.

  2. Cree un archivo de servicio con una extensión .svc con una @ ServiceHost directiva para identificar el tipo de servicio:

    <%@ServiceHost language="c#" Service="MyService" %>

  3. Copie el archivo de servicio en un directorio virtual y el ensamblado en el subdirectorio \bin de ese directorio virtual.

  4. Copie el archivo de configuración en el directorio virtual y asígnelo el nombre Web.config.

A continuación, se puede acceder a la aplicación mediante la dirección URL del archivo de servicio en la raíz de la aplicación.

Para hospedar un servicio WCF dentro de una aplicación .NET, compile el tipo de servicio en un ensamblado de biblioteca de clases al que hace referencia la aplicación y programe la aplicación para hospedar el servicio mediante la ServiceHost clase . A continuación se muestra un ejemplo de la programación básica necesaria:

string httpBaseAddress = "http://www.contoso.com:8000/";
string tcpBaseAddress = "net.tcp://www.contoso.com:8080/";

Uri httpBaseAddressUri = new Uri(httpBaseAddress);
Uri tcpBaseAddressUri = new Uri(tcpBaseAddress);

Uri[] baseAddresses = new Uri[] {
 httpBaseAddressUri,
 tcpBaseAddressUri};

using(ServiceHost host = new ServiceHost(
typeof(Service), //"Service" is the name of the service type baseAddresses))
{
     host.Open();

     […] //Wait to receive messages
     host.Close();
}

En este ejemplo se muestra cómo se especifican las direcciones de uno o varios protocolos de transporte en la construcción de un ServiceHost. Estas direcciones se conocen como direcciones base.

La dirección proporcionada para cualquier punto de conexión de un servicio WCF es una dirección relativa a una dirección base del host del punto de conexión. El host puede tener una dirección base para cada protocolo de transporte de comunicación. En la configuración de ejemplo del archivo de configuración anterior, el BasicHttpBinding seleccionado para el punto de conexión usa HTTP como protocolo de transporte, por lo que la dirección del punto de conexión, EchoService, es relativa a la dirección base HTTP del host. En el caso del host en el ejemplo anterior, la dirección base HTTP es http://www.contoso.com:8000/. Para un servicio hospedado en IIS o WAS, la dirección base es la dirección URL del archivo de servicio del servicio.

Solo los servicios hospedados en IIS o WAS, que están configurados exclusivamente con HTTP como protocolo de transporte, pueden usar la opción de modo de compatibilidad de WCF ASP.NET. La activación de esa opción requiere los pasos siguientes.

  1. El programador debe agregar el AspNetCompatibilityRequirementsAttribute atributo al tipo de servicio y especificar que ASP.NET modo de compatibilidad está permitido o necesario.

    [System.ServiceModel.Activation.AspNetCompatibilityRequirements(
          RequirementsMode=AspNetCompatibilityRequirementsMode.Require)]
    public class DerivativesCalculatorServiceType: IDerivativesCalculator
    
  2. El administrador debe configurar la aplicación para que use el modo de compatibilidad ASP.NET.

    <configuration>
         <system.serviceModel>
          <services>
          […]
          </services>
          <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
        </system.serviceModel>
    </configuration>
    

    Las aplicaciones WCF también se pueden configurar para usar .asmx como extensión para sus archivos de servicio en lugar de .svc.

    <system.web>
         <compilation>
          <compilation debug="true">
          <buildProviders>
           <remove extension=".asmx"/>
           <add extension=".asmx"
            type="System.ServiceModel.ServiceBuildProvider,
            System.ServiceModel,
            Version=3.0.0.0,
            Culture=neutral,
            PublicKeyToken=b77a5c561934e089" />
          </buildProviders>
          </compilation>
         </compilation>
    </system.web>
    

    Esa opción puede ahorrarle que tenga que modificar los clientes que están configurados para usar las direcciones URL de los archivos de servicio .asmx al modificar un servicio para usar WCF.

Desarrollo de cliente

Los clientes de ASP.NET servicios web se generan mediante la herramienta de línea de comandos, WSDL.exe, que proporciona la dirección URL del archivo .asmx como entrada. La herramienta correspondiente proporcionada por WCF es ServiceModel Metadata Utility Tool (Svcutil.exe). Genera un módulo de código con la definición del contrato de servicio y la definición de una clase de cliente WCF. También genera un archivo de configuración con la dirección y el enlace del servicio.

En la programación de un cliente de un servicio remoto, generalmente es aconsejable programar según un patrón asincrónico. El código generado por la herramienta WSDL.exe siempre admite tanto patrones sincrónicos como asincrónicos por defecto. El código generado por la herramienta de utilidad de metadatos serviceModel (Svcutil.exe) puede proporcionar cualquiera de los patrones. Proporciona el patrón sincrónico de forma predeterminada. Si se ejecuta la herramienta con el modificador /async, el código generado proporciona el patrón asincrónico.

No hay ninguna garantía de que los nombres de las clases de cliente WCF generadas por la herramienta de WSDL.exe de ASP.NET, de forma predeterminada, coincidan con los nombres de las clases de cliente wcF generadas por la herramienta Svcutil.exe. En concreto, los nombres de las propiedades de las clases que se deben serializar mediante XmlSerializer se les asigna, de forma predeterminada, el sufijo Property en el código generado por la herramienta Svcutil.exe, lo cual no ocurre con la herramienta WSDL.exe.

Representación de mensajes

Los encabezados de los mensajes SOAP enviados y recibidos por ASP.NET servicios web se pueden personalizar. Una clase se deriva de SoapHeader para definir la estructura del encabezado y, a continuación SoapHeaderAttribute , se usa para indicar la presencia del encabezado.

public class SomeProtocol : SoapHeader
{
     public long CurrentValue;
     public long Total;
}

[WebService]
public interface IEcho
{
     SomeProtocol ProtocolHeader
     {
      get;
     set;
     }

     [WebMethod]
     [SoapHeader("ProtocolHeader")]
     string PlaceOrders(PurchaseOrderType order);
}

public class Service: WebService, IEcho
{
     private SomeProtocol protocolHeader;

     public SomeProtocol ProtocolHeader
     {
         get
         {
              return this.protocolHeader;
         }

         set
         {
              this.protocolHeader = value;
         }
     }

     string PlaceOrders(PurchaseOrderType order)
     {
         long currentValue = this.protocolHeader.CurrentValue;
     }
}

WCF proporciona los atributos, MessageContractAttribute, MessageHeaderAttributey MessageBodyMemberAttribute para describir la estructura de los mensajes SOAP enviados y recibidos por un servicio.

[DataContract]
public class SomeProtocol
{
     [DataMember]
     public long CurrentValue;
     [DataMember]
     public long Total;
}

[DataContract]
public class Item
{
     [DataMember]
     public string ItemNumber;
     [DataMember]
     public decimal Quantity;
     [DataMember]
     public decimal UnitPrice;
}

[MessageContract]
public class ItemMessage
{
     [MessageHeader]
     public SomeProtocol ProtocolHeader;
     [MessageBody]
     public Item Content;
}

[ServiceContract]
public interface IItemService
{
     [OperationContract]
     public void DeliverItem(ItemMessage itemMessage);
}

Esta sintaxis produce una representación explícita de la estructura de los mensajes, mientras que la estructura de los mensajes está implícita en el código de un servicio web de ASP.NET. Además, en la sintaxis ASP.NET, los encabezados de mensaje se representan como propiedades del servicio, como la ProtocolHeader propiedad del ejemplo anterior, mientras que en la sintaxis wcF, se representan con mayor precisión como propiedades de los mensajes. Además, WCF permite agregar encabezados de mensaje a la configuración de puntos de conexión.

<service name="Service ">
     <endpoint
      address="EchoService"
      binding="basicHttpBinding"
      contract="IEchoService ">
      <headers>
      <dsig:X509Certificate
       xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
       ...
      </dsig:X509Certificate>
      </headers>
     </endpoint>
</service>

Esta opción permite evitar cualquier referencia a encabezados de protocolo de infraestructura en el código de un cliente o servicio: los encabezados se agregan a los mensajes debido a cómo se configura el punto de conexión.

Descripción del servicio

La emisión de una solicitud HTTP GET para el archivo .asmx de un servicio web de ASP.NET con la consulta WSDL hace que ASP.NET generar WSDL para describir el servicio. Devuelve que WSDL es la respuesta a la solicitud.

ASP.NET 2.0 hizo posible validar que un servicio es compatible con el Basic Profile 1.1 de la organización web de Services-Interoperability (WS-I) e insertar una declaración de conformidad en su WSDL. Esto se realiza mediante los parámetros ConformsTo y EmitConformanceClaims del atributo WebServiceBindingAttribute.

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(
     ConformsTo = WsiProfiles.BasicProfile1_1,
     EmitConformanceClaims=true)]
public interface IEcho

El WSDL que ASP.NET genera para un servicio se puede personalizar. Las personalizaciones se realizan mediante la creación de una clase derivada de ServiceDescriptionFormatExtension para agregar elementos al WSDL.

La emisión de una solicitud HTTP GET con el WSDL de consulta para el archivo .svc de un servicio WCF con un punto de conexión HTTP hospedado en IIS 51, 6.0 o WAS hace que WCF responda con WSDL para describir el servicio. La emisión de una solicitud HTTP GET con la consulta WSDL a la dirección base HTTP de un servicio hospedado dentro de una aplicación .NET tiene el mismo efecto si httpGetEnabled está establecido en true.

Sin embargo, WCF también responde a las solicitudes de WS-MetadataExchange con el WSDL que genera para describir un servicio. ASP.NET servicios web no tienen compatibilidad integrada con solicitudes de WS-MetadataExchange.

El WSDL que genera WCF se puede personalizar ampliamente. La ServiceMetadataBehavior clase proporciona algunas instalaciones para personalizar el WSDL. El WCF también se puede configurar para no generar WSDL, sino para usar un archivo WSDL estático en una dirección URL determinada.

<behaviors>
     <behavior name="DescriptionBehavior">
     <metadataPublishing
      enableMetadataExchange="true"
      enableGetWsdl="true"
      enableHelpPage="true"
      metadataLocation=
      "http://localhost/DerivativesCalculatorService/Service.WSDL"/>
     </behavior>
</behaviors>

Control de excepciones

Las excepciones no controladas en los servicios web de ASP.NET se devuelven a los clientes como errores SOAP. También puede lanzar explícitamente instancias de la clase SoapException y tener más control sobre el contenido de la falla SOAP que se transmite al cliente.

En los servicios WCF, las excepciones no controladas no se devuelven a los clientes como errores soap para evitar que la información confidencial se exponga accidentalmente a través de las excepciones. Se proporciona una configuración para que las excepciones no controladas se devuelvan a los clientes con el fin de depurar.

Para devolver los errores de SOAP a los clientes, puede iniciar las instancias del tipo genérico, FaultException<TDetail>, utilizando el tipo de contrato de datos como tipo genérico. También puede agregar FaultContractAttribute atributos a las operaciones para especificar los errores que puede producir una operación.

[DataContract]
public class MathFault
{
     [DataMember]
     public string operation;
     [DataMember]
     public string problemType;
}

[ServiceContract]
public interface ICalculator
{
     [OperationContract]
     [FaultContract(typeof(MathFault))]
     int Divide(int n1, int n2);
}

Con esto, los posibles errores podrían anunciarse en el WSDL del servicio, lo que permitiría a los desarrolladores del cliente anticipar qué errores pueden ser el resultado de una operación, y escribir las instrucciones de captura adecuadas.

try
{
     result = client.Divide(value1, value2);
}
catch (FaultException<MathFault> e)
{
 Console.WriteLine("FaultException<MathFault>: Math fault while doing "
  + e.Detail.operation
  + ". Problem: "
  + e.Detail.problemType);
}

Administración de estados

La clase usada para implementar un servicio web de ASP.NET puede derivarse de WebService.

public class Service : WebService, IEcho
{

 public string Echo(string input)
 {
  return input;
 }
}

En ese caso, la clase se puede programar para usar la propiedad Context de la WebService clase base para tener acceso a un HttpContext objeto . El HttpContext objeto se puede usar para actualizar y recuperar información de estado de la aplicación mediante su propiedad Application, y se puede usar para actualizar y recuperar información de estado de sesión mediante su propiedad Session.

ASP.NET proporciona un control considerable sobre dónde se almacena realmente la información de estado de sesión a la que se accede mediante la propiedad Session de HttpContext . Puede almacenarse en cookies, en una base de datos, en la memoria del servidor actual o en la memoria de un servidor designado. La elección se realiza en el archivo de configuración del servicio.

WCF proporciona objetos extensibles para la administración de estados. Los objetos extensibles son objetos que implementan IExtensibleObject<T>. Los objetos extensibles más importantes son ServiceHostBase y InstanceContext. ServiceHostBase permite mantener el estado de que todas las instancias de todos los tipos de servicio del mismo host pueden tener acceso, mientras InstanceContext que permite mantener el estado al que puede acceder cualquier código que se ejecute dentro de la misma instancia de un tipo de servicio.

Aquí, el tipo de servicio TradingSystem tiene un ServiceBehaviorAttribute que especifica que todas las llamadas de la misma instancia de cliente WCF se enrutan a la misma instancia del tipo de servicio.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class TradingSystem: ITradingService

La clase , DealDatadefine el estado al que se puede tener acceso cualquier código que se ejecute en la misma instancia de un tipo de servicio.

internal class DealData: IExtension<InstanceContext>
{
 public string DealIdentifier = null;
 public Trade[] Trades = null;
}

En el código del tipo de servicio que implementa una de las operaciones del contrato de servicio, se agrega un DealData objeto de estado al estado de la instancia actual del tipo de servicio.

string ITradingService.BeginDeal()
{
 string dealIdentifier = Guid.NewGuid().ToString();
 DealData state = new DealData(dealIdentifier);
 OperationContext.Current.InstanceContext.Extensions.Add(state);
 return dealIdentifier;
}

Ese objeto de estado se puede recuperar y modificar mediante el código que implementa otra de las operaciones del contrato de servicio.

void ITradingService.AddTrade(Trade trade)
{
 DealData dealData =  OperationContext.Current.InstanceContext.Extensions.Find<DealData>();
 dealData.AddTrade(trade);
}

Mientras que ASP.NET proporciona control sobre dónde se almacena realmente la información de estado de la HttpContext clase, WCF, al menos en su versión inicial, no proporciona ningún control sobre dónde se almacenan los objetos extensibles. Esto constituye la mejor razón para seleccionar el modo de compatibilidad de ASP.NET para un servicio WCF. Si la administración de estado configurable es imperativa, optar por el modo de compatibilidad de ASP.NET permite usar las instalaciones de la HttpContext clase exactamente como se usan en ASP.NET, y también para configurar dónde se almacena la información de estado administrada mediante la HttpContext clase .

Seguridad

Las opciones para proteger ASP.NET servicios web son las de proteger cualquier aplicación de IIS. Dado que las aplicaciones WCF se pueden hospedar no solo dentro de IIS, sino también dentro de cualquier archivo ejecutable de .NET, las opciones para proteger las aplicaciones WCF deben hacerse independientes de las instalaciones de IIS. Sin embargo, las funcionalidades proporcionadas para los servicios web de ASP.NET también están disponibles para los servicios WCF que se ejecutan en modo de compatibilidad de ASP.NET.

Seguridad: autenticación

IIS proporciona instalaciones para controlar el acceso a las aplicaciones mediante las que puede seleccionar el acceso anónimo o una variedad de modos de autenticación: Autenticación de Windows, Autenticación implícita, Autenticación básica y Autenticación de .NET Passport. La opción Autenticación de Windows se puede usar para controlar el acceso a ASP.NET servicios web. Sin embargo, cuando las aplicaciones WCF se hospedan en IIS, IIS debe configurarse para permitir el acceso anónimo a la aplicación, de modo que la autenticación se pueda administrar mediante WCF, que admite la autenticación de Windows entre otras opciones. Las otras opciones integradas incluyen tokens de nombre de usuario, certificados X.509, tokens SAML y tarjeta CardSpace, pero también se pueden definir mecanismos de autenticación personalizados.

Seguridad: suplantación

ASP.NET proporciona un elemento de identidad mediante el cual se puede configurar un servicio web de ASP.NET para que suplante a un usuario determinado o las credenciales del usuario que se proporcionen con la solicitud actual. Ese elemento puede utilizarse para configurar la suplantación en aplicaciones de WCF que se ejecutan en modo de compatibilidad de ASP.NET.

El sistema de configuración de WCF proporciona su propio elemento de identidad para designar a un usuario determinado para suplantar. Además, los clientes y servicios WCF se pueden configurar de forma independiente para la impersonación. Los clientes se pueden configurar para suplantar al usuario actual cuando transmiten solicitudes.

<behaviors>
     <behavior name="DerivativesCalculatorClientBehavior">
      <clientCredentials>
      <windows allowedImpersonationLevel="Impersonation"/>
      </clientCredentials>
     </behavior>
</behaviors>

Las operaciones de servicio se pueden configurar para suplantar las credenciales del usuario que se proporcionen con la solicitud actual.

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public void Receive(Message input)

Seguridad: autorización mediante listas de control de acceso

Las listas de control de acceso (ACL) se pueden usar para restringir el acceso a archivos .asmx. Sin embargo, las ACL en los archivos .svc de WCF se omiten excepto en el modo de compatibilidad de ASP.NET.

Seguridad: autorización basada en roles

La opción Autenticación de Windows de IIS se puede usar junto con el elemento de autorización proporcionado por el lenguaje de configuración de ASP.NET para facilitar la autorización basada en roles para ASP.NET servicios web basados en los grupos de Windows a los que se asignan los usuarios. ASP.NET 2.0 introdujo un mecanismo de autorización basado en roles más general: proveedores de roles.

Los proveedores de roles son clases que implementan una interfaz básica para consultar los roles a los que se asigna un usuario, pero cada proveedor de roles sabe cómo recuperar esa información de un origen diferente. ASP.NET 2.0 proporciona un proveedor de roles que puede recuperar asignaciones de roles de una base de datos de Microsoft SQL Server y otra que pueda recuperar asignaciones de roles del Administrador de autorización de Windows Server 2003.

El mecanismo del proveedor de roles se puede usar de forma independiente de ASP.NET en cualquier aplicación .NET, incluida una aplicación WCF. La siguiente configuración de ejemplo para una aplicación WCF muestra cómo el uso de un proveedor de roles de ASP.NET es una opción seleccionada mediante .ServiceAuthorizationBehavior

<system.serviceModel>
     <services>
         <service name="Service.ResourceAccessServiceType"
             behaviorConfiguration="ServiceBehavior">
             <endpoint
              address="ResourceAccessService"
              binding="wsHttpBinding"
              contract="Service.IResourceAccessContract"/>
         </service>
     </services>
     <behaviors>
       <behavior name="ServiceBehavior">
       <serviceAuthorization principalPermissionMode="UseAspNetRoles"/>
      </behavior>
     </behaviors>
</system.serviceModel>

Seguridad: Autorización basada en declaraciones

Una de las innovaciones más importantes de WCF es su soporte completo para autorizar el acceso a recursos protegidos en función de las declaraciones. Las reclamaciones constan de un tipo, un derecho y un valor, como una licencia de conducir, por ejemplo. Hace un conjunto de reclamaciones sobre el portador, una de las cuales es la fecha de nacimiento del portador. El tipo de esa notificación es la fecha de nacimiento, mientras que el valor de la notificación es la fecha de nacimiento del conductor. El derecho que una reclamación concede al portador especifica lo que el portador puede hacer con el valor de la reclamación. En el caso de la reclamación de la fecha de nacimiento del conductor, el derecho es posesión: el conductor posee esa fecha de nacimiento, pero no, por ejemplo, modificarla. La autorización basada en notificaciones engloba a la autorización basada en funciones, ya que las funciones son un tipo de notificación.

La autorización basada en notificaciones se realiza comparando un conjunto de notificaciones con los requisitos de acceso de la operación y, en función del resultado de esa comparación, conceder o denegar el acceso a la operación. En WCF, puede especificar una clase que se utilizará para ejecutar la autorización basada en reclamaciones, nuevamente asignando un valor a la ServiceAuthorizationManager propiedad de ServiceAuthorizationBehavior.

<behaviors>
     <behavior name='ServiceBehavior'>
     <serviceAuthorization
     serviceAuthorizationManagerType=
                   'Service.AccessChecker, Service' />
     </behavior>
</behaviors>

Las clases usadas para ejecutar la autorización basada en notificaciones deben derivar de ServiceAuthorizationManager, que tiene solo un método para invalidar, AccessCheck(). WCF llama a ese método siempre que se invoca una operación del servicio y proporciona un objeto OperationContext, que tiene las notificaciones para el usuario en su propiedad ServiceSecurityContext.AuthorizationContext. WCF realiza el trabajo de ensamblar notificaciones sobre el usuario desde cualquier token de seguridad que el usuario proporcionó para la autenticación, lo que deja la tarea de evaluar si esas notificaciones son suficientes para la operación en cuestión.

Que WCF ensambla automáticamente las notificaciones de cualquier tipo de token de seguridad es una innovación muy significativa, ya que hace que el código para la autorización se base en las notificaciones completamente independientes del mecanismo de autenticación. Por el contrario, la autorización mediante ACL o roles en ASP.NET está estrechamente vinculada a la autenticación de Windows.

Seguridad: Confidencialidad

La confidencialidad de los mensajes intercambiados con ASP.NET servicios web se puede garantizar en el nivel de transporte configurando la aplicación dentro de IIS para usar el Protocolo seguro de transferencia de hipertexto (HTTPS). Lo mismo se puede hacer para las aplicaciones WCF hospedadas en IIS. Sin embargo, las aplicaciones WCF hospedadas fuera de IIS también se pueden configurar para usar un protocolo de transporte seguro. Más importante, las aplicaciones WCF también se pueden configurar para proteger los mensajes antes de transportarlos mediante el protocolo WS-Security. Proteger solo el cuerpo de un mensaje mediante WS-Security permite que se transmita confidencialmente a través de intermediarios antes de llegar a su destino final.

Globalización

El ASP.NET idioma de configuración permite especificar la referencia cultural de los servicios individuales. WCF no admite esa configuración excepto en ASP.NET modo de compatibilidad. Para localizar un servicio WCF que no utiliza el modo de compatibilidad de ASP.NET, compile el tipo de servicio en los ensamblados específicos de la referencia cultural y defina puntos de conexión específicos de la referencia cultural distintos para cada ensamblado específico de la referencia cultural.

Consulte también