Comparando ASP.NET Web Services com WCF com base no desenvolvimento
O Windows Communication Foundation (WCF) tem uma opção de modo de compatibilidade ASP.NET para permitir que os aplicativos WCF sejam programados e configurados como ASP.NET serviços Web e imitem seu comportamento. As seções a seguir comparam ASP.NET serviços Web e WCF com base no que é necessário para desenvolver aplicativos usando ambas as tecnologias.
Representação de dados
O desenvolvimento de um serviço Web com ASP.NET normalmente começa com a definição de quaisquer tipos de dados complexos que o serviço deve usar. ASP.NET depende da XmlSerializer tradução de dados representados por tipos do .NET Framework para XML para transmissão de ou para um serviço e para traduzir dados recebidos como XML em objetos do .NET Framework. Definir os tipos de dados complexos que um serviço de ASP.NET deve usar requer a definição de classes do .NET Framework que o XmlSerializer pode serializar de e para XML. Essas classes podem ser escritas manualmente ou geradas a partir de definições dos tipos no esquema XML usando o utilitário de suporte a esquemas XML/tipos de dados de linha de comando, xsd.exe.
A seguir está uma lista dos principais problemas a serem conhecidos ao definir classes do .NET Framework que podem XmlSerializer serializar de e para XML:
Somente os campos públicos e as propriedades dos objetos do .NET Framework são convertidos em XML.
As instâncias de classes de coleção podem ser serializadas em XML somente se as classes implementarem a IEnumerable interface ou ICollection .
As classes que implementam a IDictionary interface, como Hashtable, não podem ser serializadas em XML.
Os muitos tipos de atributos no System.Xml.Serialization namespace podem ser adicionados a uma classe do .NET Framework e seus membros para controlar como as instâncias da classe são representadas em XML.
O desenvolvimento de aplicativos WCF geralmente também começa com a definição de tipos complexos. WCF pode ser feito para usar os mesmos tipos de .NET Framework como ASP.NET serviços Web.
O WCFDataContractAttribute e DataMemberAttribute pode ser adicionado aos tipos do .NET Framework para indicar que instâncias do tipo devem ser serializadas em XML e quais campos ou propriedades específicas do tipo devem ser serializados, conforme mostrado no código de exemplo a seguir.
//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;
}
}
}
O DataContractAttribute significa que zero ou mais campos ou propriedades de um tipo devem ser serializados, enquanto o DataMemberAttribute indica que um determinado campo ou propriedade deve ser serializado. O DataContractAttribute pode ser aplicado a uma classe ou estrutura. O DataMemberAttribute pode ser aplicado a um campo ou uma propriedade, e os campos e propriedades aos quais o atributo é aplicado podem ser públicos ou privados. As instâncias de tipos que têm o DataContractAttribute aplicado a elas são chamadas de contratos de dados no WCF. Eles são serializados em XML usando DataContractSerializer.
A seguir está uma lista das diferenças importantes entre usar o DataContractSerializer e usar o XmlSerializer e os vários atributos do System.Xml.Serialization namespace.
Os XmlSerializer e os atributos do namespace são projetados para permitir que você mapeie tipos do System.Xml.Serialization .NET Framework para qualquer tipo válido definido no esquema XML e, portanto, eles fornecem um controle muito preciso sobre como um tipo é representado em XML. O DataContractSerializer, DataContractAttribute e DataMemberAttribute fornecem muito pouco controle sobre como um tipo é representado em XML. Você só pode especificar os namespaces e nomes usados para representar o tipo e seus campos ou propriedades no XML, e a sequência na qual os campos e propriedades aparecem no XML:
[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 o resto sobre a estrutura do XML usado para representar o tipo .NET é determinado pelo DataContractSerializer.
Ao não permitir muito controle sobre como um tipo deve ser representado em XML, o processo de serialização torna-se altamente previsível para o DataContractSerializer, e, portanto, mais fácil de otimizar. Um benefício prático do design do é o DataContractSerializer melhor desempenho, aproximadamente dez por cento melhor desempenho.
Os atributos para uso com o XmlSerializer não indicam quais campos ou propriedades do tipo são serializados em XML, enquanto o DataMemberAttribute para uso com o DataContractSerializer mostra explicitamente quais campos ou propriedades são serializados. Portanto, os contratos de dados são contratos explícitos sobre a estrutura dos dados que um aplicativo deve enviar e receber.
O XmlSerializer só pode traduzir os membros públicos de um objeto .NET em XML, o DataContractSerializer pode traduzir os membros de objetos em XML, independentemente dos modificadores de acesso desses membros.
Como consequência de ser capaz de serializar os membros não-públicos de tipos em XML, o DataContractSerializer tem menos restrições sobre a variedade de tipos .NET que ele pode serializar em XML. Em particular, ele pode traduzir em tipos XML como Hashtable que implementam a IDictionary interface. É DataContractSerializer muito mais provável que o seja capaz de serializar as instâncias de qualquer tipo .NET pré-existente em XML sem ter que modificar a definição do tipo ou desenvolver um wrapper para ele.
Outra consequência da possibilidade de DataContractSerializer aceder aos membros não públicos de um tipo é que requer confiança total, ao passo que o XmlSerializer não exige. A permissão de acesso ao código Full Trust dá acesso completo a todos os recursos em uma máquina que podem ser acessados usando as credenciais sob as quais o código está sendo executado. Essa opção deve ser usada com cuidado, pois o código totalmente confiável acessa todos os recursos em sua máquina.
O DataContractSerializer incorpora algum suporte para versionamento:
O DataMemberAttribute tem uma IsRequired propriedade que pode ser atribuída um valor false para membros que são adicionados a novas versões de um contrato de dados que não estavam presentes em versões anteriores, permitindo assim que aplicativos com a versão mais recente do contrato possam processar versões anteriores.
Ao ter um contrato de dados implementar a IExtensibleDataObject interface, pode-se permitir que os DataContractSerializer membros passem definidos em versões mais recentes de um contrato de dados através de aplicativos com versões anteriores do contrato.
Apesar de todas as diferenças, o XML no qual o XmlSerializer serializa um tipo por padrão é semanticamente idêntico ao XML no qual o DataContractSerializer serializa um tipo, desde que o namespace para o XML seja explicitamente definido. A classe a seguir, que tem atributos para uso com ambos os serializadores, é convertida em XML semanticamente idêntico pelo XmlSerializer e pelo 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;
}
O SDK (Software Development Kit) do Windows inclui uma ferramenta de linha de comando chamada ServiceModel Metadata Utility Tool (Svcutil.exe). Como a ferramenta xsd.exe usada com ASP.NET Web Services, Svcutil.exe pode gerar definições de tipos de dados .NET a partir do esquema XML. Os tipos são contratos de dados se o DataContractSerializer pode emitir XML no formato definido pelo esquema XML, caso contrário, eles são destinados à serialização usando o XmlSerializer. Svcutil.exe também pode gerar um esquema XML a partir de contratos de dados usando sua dataContractOnly
opção.
Nota
Embora ASP.NET serviços Web usem o XmlSerializermodo de compatibilidade ASP.NET e WCF faça com que os serviços WCF imitem o comportamento de ASP.NET serviços Web, a opção de compatibilidade ASP.NET não restringe o uso do XmlSerializer. Ainda é possível usar o DataContractSerializer com serviços em execução no modo de compatibilidade ASP.NET.
Desenvolvimento de Serviços
Para desenvolver um serviço usando ASP.NET, tem sido habitual adicionar o WebService atributo a uma classe e a WebMethodAttribute qualquer um dos métodos dessa classe que devem ser operações do serviço:
[WebService]
public class Service : T:System.Web.Services.WebService
{
[WebMethod]
public string Echo(string input)
{
return input;
}
}
ASP.NET 2.0 introduziu a opção de adicionar o atributo WebService e WebMethodAttribute a uma interface em vez de uma classe, e escrever uma classe para implementar a interface:
[WebService]
public interface IEcho
{
[WebMethod]
string Echo(string input);
}
public class Service : IEcho
{
public string Echo(string input)
{
return input;
}
}
O uso dessa opção é preferível, porque a interface com o WebService atributo constitui um contrato para as operações executadas pelo serviço que pode ser reutilizado com várias classes que podem implementar esse mesmo contrato de maneiras diferentes.
Um serviço WCF é fornecido definindo um ou mais pontos de extremidade WCF. Um ponto de extremidade é definido por um endereço, uma vinculação e um contrato de serviço. O endereço define onde o serviço está localizado. A associação especifica como se comunicar com o serviço. O contrato de serviço define as operações que o serviço pode executar.
O contrato de serviço é geralmente definido primeiro, adicionando ServiceContractAttribute e OperationContractAttribute a uma interface:
[ServiceContract]
public interface IEcho
{
[OperationContract]
string Echo(string input);
}
O ServiceContractAttribute especifica que a interface define um contrato de serviço WCF e o OperationContractAttribute indica qual, se houver, dos métodos da interface definem as operações do contrato de serviço.
Uma vez definido um contrato de serviço, ele é implementado em uma classe, fazendo com que a classe implemente a interface pela qual o contrato de serviço é definido:
public class Service : IEcho
{
public string Echo(string input)
{
return input;
}
}
Uma classe que implementa um contrato de serviço é referida como um tipo de serviço no WCF.
A próxima etapa é associar um endereço e uma associação a um tipo de serviço. Isso geralmente é feito em um arquivo de configuração, editando o arquivo diretamente ou usando um editor de configuração fornecido com o WCF. Aqui está um exemplo de um arquivo de configuração.
<?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>
A associação especifica o conjunto de protocolos para comunicação com o aplicativo. A tabela a seguir lista as associações fornecidas pelo sistema que representam opções comuns.
Nome | Propósito |
---|---|
BasicHttpBinding | Interoperabilidade com serviços Web e clientes que suportam o WS-BasicProfile 1.1 e Basic Security Profile 1.0. |
WSHttpBinding | Interoperabilidade com serviços Web e clientes que suportam os protocolos WS-* sobre HTTP. |
WSDualHttpBinding | Comunicação HTTP duplex, pela qual o recetor de uma mensagem inicial não responde diretamente ao remetente inicial, mas pode transmitir qualquer número de respostas durante um período de tempo usando HTTP em conformidade com os protocolos WS-*. |
WSFederationBinding | Comunicação HTTP, na qual o acesso aos recursos de um serviço pode ser controlado com base em credenciais emitidas por um provedor de credenciais explicitamente identificado. |
NetTcpBinding | Comunicação segura, confiável e de alto desempenho entre entidades de software WCF em uma rede. |
NetNamedPipeBinding | Comunicação segura, confiável e de alto desempenho entre entidades de software WCF na mesma máquina. |
NetMsmqBinding | Comunicação entre entidades de software WCF usando MSMQ. |
MsmqIntegrationBinding | Comunicação entre uma entidade de software WCF e outra entidade de software usando MSMQ. |
NetPeerTcpBinding | Comunicação entre entidades de software WCF usando a rede ponto a ponto do Windows. |
A ligação fornecida pelo sistema, BasicHttpBinding, incorpora o conjunto de protocolos suportados por ASP.NET serviços Web.
Associações personalizadas para aplicativos WCF são facilmente definidas como coleções das classes de elemento de ligação que o WCF usa para implementar protocolos individuais. Novos elementos de vinculação podem ser escritos para representar protocolos adicionais.
O comportamento interno dos tipos de serviço pode ser ajustado usando as propriedades de uma família de classes chamadas comportamentos. Aqui, a ServiceBehaviorAttribute classe é usada para especificar que o tipo de serviço deve ser multithreaded.
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
public class DerivativesCalculatorServiceType: IDerivativesCalculator
Alguns comportamentos, como ServiceBehaviorAttribute, são atributos. Outros, aqueles com propriedades que os administradores gostariam de definir, podem ser modificados na configuração de um aplicativo.
Em tipos de serviço de programação, o uso freqüente é feito da OperationContext classe. Sua propriedade static Current fornece acesso a informações sobre o contexto no qual uma operação está sendo executada. OperationContext é semelhante às HttpContext classes e ContextUtil .
Alojamento
ASP.NET serviços Web são compilados em um assembly de biblioteca de classes. É fornecido um arquivo chamado arquivo de serviço que tem a extensão .asmx e contém uma @ WebService
diretiva que identifica a classe que contém o código para o serviço e o assembly no qual ele está localizado.
<%@ WebService Language="C#" Class="Service,ServiceAssembly" %>
O arquivo de serviço é copiado para uma raiz de aplicativo ASP.NET no IIS (Serviços de Informações da Internet) e o assembly é copiado para o subdiretório \bin dessa raiz do aplicativo. O aplicativo é então acessível usando o localizador uniforme de recursos (URL) do arquivo de serviço na raiz do aplicativo.
Os serviços WCF podem ser prontamente hospedados no IIS 5.1 ou 6.0, o Serviço de Ativação de Processos do Windows (WAS) fornecido como parte do IIS 7.0 e em qualquer aplicativo .NET. Para hospedar um serviço no IIS 5.1 ou 6.0, o serviço deve usar HTTP como o protocolo de transporte de comunicações.
Para hospedar um serviço no IIS 5.1, 6.0 ou no WAS, use as seguintes etapas:
Compile o tipo de serviço em um assembly de biblioteca de classes.
Crie um arquivo de serviço com uma extensão .svc com uma
@ ServiceHost
diretiva para identificar o tipo de serviço:<%@ServiceHost language="c#" Service="MyService" %>
Copie o arquivo de serviço para um diretório virtual e o assembly para o subdiretório \bin desse diretório virtual.
Copie o arquivo de configuração para o diretório virtual e nomeie-o Web.config.
O aplicativo é então acessível usando a URL do arquivo de serviço na raiz do aplicativo.
Para hospedar um serviço WCF em um aplicativo .NET, compile o tipo de serviço em um assembly de biblioteca de classes referenciado pelo aplicativo e programe o aplicativo para hospedar o serviço usando a ServiceHost classe. Segue-se um exemplo da programação básica necessária:
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();
}
Este exemplo mostra como os endereços de um ou mais protocolos de transporte são especificados na construção de um ServiceHostarquivo . Esses endereços são chamados de endereços base.
O endereço fornecido para qualquer ponto de extremidade de um serviço WCF é um endereço relativo a um endereço base do host do ponto de extremidade. O host pode ter um endereço base para cada protocolo de transporte de comunicação. Na configuração de exemplo no arquivo de configuração anterior, o BasicHttpBinding selecionado para o ponto de extremidade usa HTTP como o protocolo de transporte, portanto, o endereço do ponto de extremidade, EchoService
, é relativo ao endereço base HTTP do host. No caso do host no exemplo anterior, o endereço base HTTP é http://www.contoso.com:8000/
. Para um serviço hospedado no IIS ou WAS, o endereço base é a URL do arquivo de serviço do serviço.
Somente serviços hospedados no IIS ou WAS, e que são configurados com HTTP como o protocolo de transporte exclusivamente, podem ser feitos para usar WCF ASP.NET opção de modo de compatibilidade. Ativar essa opção requer as etapas a seguir.
O programador deve adicionar o AspNetCompatibilityRequirementsAttribute atributo ao tipo de serviço e especificar que ASP.NET modo de compatibilidade é permitido ou necessário.
[System.ServiceModel.Activation.AspNetCompatibilityRequirements( RequirementsMode=AspNetCompatibilityRequirementsMode.Require)] public class DerivativesCalculatorServiceType: IDerivativesCalculator
O administrador deve configurar o aplicativo para usar o modo de compatibilidade ASP.NET.
<configuration> <system.serviceModel> <services> […] </services> <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> </system.serviceModel> </configuration>
Os aplicativos WCF também podem ser configurados para usar .asmx como a extensão para seus arquivos de serviço em vez 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>
Essa opção pode evitar que você precise modificar clientes configurados para usar as URLs de arquivos de serviço .asmx ao modificar um serviço para usar WCF.
Desenvolvimento de Clientes
Os clientes para serviços Web ASP.NET são gerados usando a ferramenta de linha de comando, WSDL.exe, que fornece a URL do arquivo .asmx como entrada. A ferramenta correspondente fornecida pelo WCF é ServiceModel Metadata Utility Tool (Svcutil.exe). Ele gera um módulo de código com a definição do contrato de serviço e a definição de uma classe de cliente WCF. Ele também gera um arquivo de configuração com o endereço e a vinculação do serviço.
Na programação de um cliente de um serviço remoto é geralmente aconselhável programar de acordo com um padrão assíncrono. O código gerado pela ferramenta WSDL.exe sempre fornece um padrão síncrono e assíncrono por padrão. O código gerado pela ServiceModel Metadata Utility Tool (Svcutil.exe) pode fornecer qualquer padrão. Ele fornece o padrão síncrono por padrão. Se a ferramenta for executada com o /async
switch, o código gerado fornecerá o padrão assíncrono.
Não há garantia de que os nomes nas classes de cliente WCF geradas pela ferramenta WSDL.exe do ASP.NET, por padrão, correspondam aos nomes nas classes de cliente WCF geradas pela ferramenta Svcutil.exe. Em particular, os nomes das propriedades das classes que devem ser serializadas usando o XmlSerializer são, por padrão, dado o sufixo Propriedade no código gerado pela ferramenta Svcutil.exe, o que não é o caso da ferramenta WSDL.exe.
Representação de mensagens
Os cabeçalhos das mensagens SOAP enviadas e recebidas por ASP.NET serviços Web podem ser personalizados. Uma classe é derivada de SoapHeader para definir a estrutura do cabeçalho e, em seguida, o SoapHeaderAttribute é usado para indicar a presença do cabeçalho.
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;
}
}
O WCF fornece os atributos, MessageContractAttribute, MessageHeaderAttributee MessageBodyMemberAttribute para descrever a estrutura das mensagens SOAP enviadas e recebidas por um serviço.
[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);
}
Essa sintaxe produz uma representação explícita da estrutura das mensagens, enquanto a estrutura das mensagens é implícita pelo código de um serviço Web ASP.NET. Além disso, na sintaxe ASP.NET, os cabeçalhos de mensagem são representados como propriedades do serviço, como a ProtocolHeader
propriedade no exemplo anterior, enquanto na sintaxe WCF, eles são representados com mais precisão como propriedades de mensagens. Além disso, o WCF permite que cabeçalhos de mensagens sejam adicionados à configuração de pontos de extremidade.
<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>
Essa opção permite evitar qualquer referência a cabeçalhos de protocolo de infraestrutura no código de um cliente ou serviço: os cabeçalhos são adicionados às mensagens devido à forma como o ponto de extremidade é configurado.
Descrição do Serviço
A emissão de uma solicitação HTTP GET para o arquivo .asmx de um serviço Web ASP.NET com a consulta WSDL faz com que ASP.NET gere WSDL para descrever o serviço. Ele retorna esse WSDL como a resposta à solicitação.
ASP.NET 2.0 tornou possível validar que um serviço é compatível com o Perfil Básico 1.1 da Web Services-Interoperability Organization (WS-I) e inserir uma declaração de que o serviço é compatível com seu WSDL. Isso é feito usando os ConformsTo
parâmetros e EmitConformanceClaims
do WebServiceBindingAttribute atributo.
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(
ConformsTo = WsiProfiles.BasicProfile1_1,
EmitConformanceClaims=true)]
public interface IEcho
O WSDL que ASP.NET gera para um serviço pode ser personalizado. As personalizações são feitas criando uma classe derivada de ServiceDescriptionFormatExtension para adicionar itens ao WSDL.
Emitir uma solicitação HTTP GET com a consulta WSDL para o arquivo .svc de um serviço WCF com um ponto de extremidade HTTP hospedado no IIS 51, 6.0 ou WAS faz com que o WCF responda com WSDL para descrever o serviço. Emitir uma solicitação HTTP GET com a consulta WSDL para o endereço base HTTP de um serviço hospedado em um aplicativo .NET terá o mesmo efeito se httpGetEnabled estiver definido como true.
No entanto, o WCF também responde a solicitações WS-MetadataExchange com WSDL que ele gera para descrever um serviço. ASP.NET serviços Web não têm suporte interno para solicitações WS-MetadataExchange.
O WSDL que o WCF gera pode ser amplamente personalizado. A ServiceMetadataBehavior classe fornece alguns recursos para personalizar o WSDL. O WCF também pode ser configurado para não gerar WSDL, mas sim para usar um arquivo WSDL estático em uma determinada URL.
<behaviors>
<behavior name="DescriptionBehavior">
<metadataPublishing
enableMetadataExchange="true"
enableGetWsdl="true"
enableHelpPage="true"
metadataLocation=
"http://localhost/DerivativesCalculatorService/Service.WSDL"/>
</behavior>
</behaviors>
Processamento de Exceções
Nos serviços Web ASP.NET, as exceções não tratadas são retornadas aos clientes como falhas SOAP. Você também pode lançar explicitamente instâncias da SoapException classe e ter mais controle sobre o conteúdo da falha SOAP que é transmitida ao cliente.
Nos serviços WCF, as exceções não tratadas não são retornadas aos clientes como falhas SOAP para evitar que informações confidenciais sejam expostas inadvertidamente por meio das exceções. Uma definição de configuração é fornecida para que as exceções não tratadas sejam retornadas aos clientes para fins de depuração.
Para retornar falhas SOAP aos clientes, você pode lançar instâncias do tipo genérico, FaultException<TDetail>, usando o tipo de contrato de dados como o tipo genérico. Você também pode adicionar FaultContractAttribute atributos a operações para especificar as falhas que uma operação pode produzir.
[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);
}
Isso resulta nas possíveis falhas anunciadas no WSDL para o serviço, permitindo que os programadores clientes antecipem quais falhas podem resultar de uma operação e escrevam as instruções de captura apropriadas.
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);
}
Gestão do Estado
A classe usada para implementar um serviço Web ASP.NET pode ser derivada de WebService.
public class Service : WebService, IEcho
{
public string Echo(string input)
{
return input;
}
}
Nesse caso, a classe pode ser programada para usar a WebService propriedade Context da classe base para acessar um HttpContext objeto. O HttpContext objeto pode ser usado para atualizar e recuperar informações de estado do aplicativo usando sua propriedade Application e pode ser usado para atualizar e recuperar informações de estado da sessão usando sua propriedade Session.
ASP.NET fornece um controle considerável sobre onde as informações de estado da sessão acessadas usando a propriedade Session do HttpContext são realmente armazenadas. Pode ser armazenado em cookies, numa base de dados, na memória do servidor atual ou na memória de um servidor designado. A escolha é feita no arquivo de configuração do serviço.
O WCF fornece objetos extensíveis para gerenciamento de estado. Objetos extensíveis são objetos que implementam IExtensibleObject<T>o . Os objetos extensíveis mais importantes são ServiceHostBase e InstanceContext. ServiceHostBase
permite manter o estado que todas as instâncias de todos os tipos de serviço no mesmo host podem acessar, enquanto InstanceContext
permite manter o estado que pode ser acessado por qualquer código em execução na mesma instância de um tipo de serviço.
Aqui, o tipo de serviço, TradingSystem
, tem um ServiceBehaviorAttribute que especifica que todas as chamadas da mesma instância de cliente WCF são roteadas para a mesma instância do tipo de serviço.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class TradingSystem: ITradingService
A classe, DealData
, define o estado que pode ser acessado por qualquer código em execução na mesma instância de um tipo de serviço.
internal class DealData: IExtension<InstanceContext>
{
public string DealIdentifier = null;
public Trade[] Trades = null;
}
No código do tipo de serviço que implementa uma das operações do contrato de serviço, um DealData
objeto de estado é adicionado ao estado da instância atual do tipo de serviço.
string ITradingService.BeginDeal()
{
string dealIdentifier = Guid.NewGuid().ToString();
DealData state = new DealData(dealIdentifier);
OperationContext.Current.InstanceContext.Extensions.Add(state);
return dealIdentifier;
}
Esse objeto de estado pode então ser recuperado e modificado pelo código que implementa outra das operações do contrato de serviço.
void ITradingService.AddTrade(Trade trade)
{
DealData dealData = OperationContext.Current.InstanceContext.Extensions.Find<DealData>();
dealData.AddTrade(trade);
}
Enquanto ASP.NET fornece controle sobre onde as informações de estado na classe são realmente armazenadas, o HttpContext WCF, pelo menos em sua versão inicial, não fornece controle sobre onde os objetos extensíveis são armazenados. Essa constitui a melhor razão para selecionar o modo de compatibilidade ASP.NET para um serviço WCF. Se o gerenciamento de estado configurável for imperativo, optar pelo modo de compatibilidade ASP.NET permite que você use os recursos da classe exatamente como eles são usados em ASP.NET e também configure onde as informações de estado gerenciadas HttpContext usando a HttpContext classe são armazenadas.
Segurança
As opções para proteger ASP.NET serviços Web são aquelas para proteger qualquer aplicativo do IIS. Como os aplicativos WCF podem ser hospedados não apenas no IIS, mas também em qualquer executável .NET, as opções para proteger aplicativos WCF devem ser independentes dos recursos do IIS. No entanto, os recursos fornecidos para ASP.NET serviços Web também estão disponíveis para serviços WCF executados no modo de compatibilidade ASP.NET.
Segurança: Autenticação
O IIS fornece recursos para controlar o acesso a aplicativos pelos quais você pode selecionar o acesso anônimo ou uma variedade de modos de autenticação: Autenticação do Windows, Autenticação Digest, Autenticação Básica e Autenticação do .NET Passport. A opção Autenticação do Windows pode ser usada para controlar o acesso a ASP.NET serviços Web. No entanto, quando os aplicativos WCF são hospedados no IIS, o IIS deve ser configurado para permitir acesso anônimo ao aplicativo, para que a autenticação possa ser gerenciada pelo próprio WCF, que oferece suporte à autenticação do Windows entre várias outras opções. As outras opções internas incluem tokens de nome de usuário, certificados X.509, tokens SAML e cartão CardSpace, mas mecanismos de autenticação personalizados também podem ser definidos.
Segurança: Falsificação de identidade
ASP.NET fornece um elemento de identidade pelo qual um serviço Web ASP.NET pode ser feito para representar um usuário específico ou quaisquer credenciais de usuário fornecidas com a solicitação atual. Esse elemento pode ser usado para configurar a representação em aplicativos WCF em execução no modo de compatibilidade ASP.NET.
O sistema de configuração WCF fornece seu próprio elemento de identidade para designar um usuário específico para representar. Além disso, os clientes e serviços WCF podem ser configurados de forma independente para representação. Os clientes podem ser configurados para representar o usuário atual quando transmitem solicitações.
<behaviors>
<behavior name="DerivativesCalculatorClientBehavior">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation"/>
</clientCredentials>
</behavior>
</behaviors>
As operações de serviço podem ser configuradas para representar as credenciais do usuário fornecidas com a solicitação atual.
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public void Receive(Message input)
Segurança: Autorização usando listas de controle de acesso
As ACLs (Listas de Controle de Acesso) podem ser usadas para restringir o acesso a arquivos .asmx. No entanto, ACLs em arquivos WCF .svc são ignoradas, exceto no modo de compatibilidade ASP.NET.
Segurança: Autorização baseada em função
A opção Autenticação do Windows do IIS pode ser usada em conjunto com o elemento de autorização fornecido pela linguagem de configuração ASP.NET para facilitar a autorização baseada em função para serviços Web ASP.NET com base nos grupos do Windows aos quais os usuários estão atribuídos. ASP.NET 2.0 introduziu um mecanismo de autorização baseado em funções mais geral: provedores de função.
Provedores de função são classes que implementam uma interface básica para perguntar sobre as funções às quais um usuário está atribuído, mas cada provedor de função sabe como recuperar essas informações de uma fonte diferente. O ASP.NET 2.0 fornece um provedor de função que pode recuperar atribuições de função de um banco de dados do Microsoft SQL Server e outro que pode recuperar atribuições de função do Gerenciador de Autorização do Windows Server 2003.
O mecanismo do provedor de função pode realmente ser usado independentemente de ASP.NET em qualquer aplicativo .NET, incluindo um aplicativo WCF. A configuração de exemplo a seguir para um aplicativo WCF mostra como o uso de um provedor de função ASP.NET é uma opção selecionada por meio do 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>
Segurança: Autorização baseada em declarações
Uma das inovações mais importantes do WCF é seu suporte completo para autorizar o acesso a recursos protegidos com base em declarações. As reivindicações consistem em um tipo, um direito e um valor, uma carteira de motorista, por exemplo. Faz um conjunto de reivindicações sobre o portador, uma das quais é a data de nascimento do portador. O tipo desse sinistro é a data de nascimento, enquanto o valor do sinistro é a data de nascimento do condutor. O direito que um crédito confere ao portador especifica o que este pode fazer com o valor do crédito. No caso da reivindicação da data de nascimento do condutor, o direito é a posse: o condutor possui essa data de nascimento, mas não pode, por exemplo, alterá-la. A autorização baseada em declarações inclui a autorização baseada em função, porque as funções são um tipo de declaração.
A autorização baseada em declarações é realizada comparando um conjunto de declarações com os requisitos de acesso da operação e, dependendo do resultado dessa comparação, concedendo ou negando acesso à operação. No WCF, você pode especificar uma classe a ser usada para executar a autorização baseada em declarações, mais uma vez atribuindo um valor à ServiceAuthorizationManager
propriedade de ServiceAuthorizationBehavior.
<behaviors>
<behavior name='ServiceBehavior'>
<serviceAuthorization
serviceAuthorizationManagerType=
'Service.AccessChecker, Service' />
</behavior>
</behaviors>
As classes usadas para executar a autorização baseada em declarações devem derivar do ServiceAuthorizationManager, que tem apenas um método para substituir, AccessCheck()
. O WCF chama esse método sempre que uma operação do serviço é invocada e fornece um OperationContext objeto, que tem as declarações para o usuário em sua ServiceSecurityContext.AuthorizationContext
propriedade. O WCF faz o trabalho de reunir declarações sobre o usuário a partir de qualquer token de segurança que o usuário forneceu para autenticação, o que deixa a tarefa de avaliar se essas declarações são suficientes para a operação em questão.
O fato de o WCF reunir automaticamente declarações de qualquer tipo de token de segurança é uma inovação altamente significativa, porque torna o código para autorização baseado nas declarações totalmente independente do mecanismo de autenticação. Por outro lado, a autorização usando ACLs ou funções no ASP.NET está intimamente ligada à autenticação do Windows.
Segurança: Confidencialidade
A confidencialidade das mensagens trocadas com ASP.NET serviços Web pode ser garantida no nível de transporte configurando o aplicativo no IIS para usar o protocolo HTTPS (Secure Hypertext Transfer Protocol). O mesmo pode ser feito para aplicativos WCF hospedados no IIS. No entanto, os aplicativos WCF hospedados fora do IIS também podem ser configurados para usar um protocolo de transporte seguro. Mais importante, os aplicativos WCF também podem ser configurados para proteger as mensagens antes que elas sejam transportadas, usando o protocolo WS-Security. Proteger apenas o corpo de uma mensagem usando o WS-Security permite que ela seja transmitida confidencialmente entre intermediários antes de chegar ao seu destino final.
Globalização
A linguagem de configuração ASP.NET permite especificar a cultura para serviços individuais. O WCF não suporta essa definição de configuração, exceto no modo de compatibilidade ASP.NET. Para localizar um serviço WCF que não usa ASP.NET modo de compatibilidade, compile o tipo de serviço em assemblies específicos de cultura e tenha pontos de extremidade específicos de cultura separados para cada assembly específico de cultura.