Desenvolvimento - WCF/WPF
A importância dos Namespaces em serviços
Para gerar um serviço WCF da forma politicamente correta, é necessário criarmos uma classe que representará o serviço, e implementar nela a Interface que é considerada como contrato do serviço.
por Israel AécePara gerar um serviço WCF da forma politicamente correta, é necessário criarmos uma classe que representará o serviço, e implementar nela a Interface que é considerada como contrato do serviço. Você não está restrito em uma relação um para um, ou seja, você pode implementar quantas Interfaces quiser na classe que representa o serviço. Os membros expostos por essas Interfaces, somente serão propagados para o cliente se você mencioná-los durante a criação de um endpoint.
A partir do momento que você pode receber Interfaces criadas por outros membros do time, ou até mesmo por outras empresas, há a possibilidade de haver nomes de Interfaces e de membros iguais. Quando isso acontece, podemos utilizar um recurso fornecido pela própria linguagem, que é a implementação explícita da Interface, e os conflitos de nomenclatura não ocorrem.
Como essa classe trata-se de um serviço WCF, se utilizarmos esse recurso tudo compilará sem problemas, mas ao rodar o serviço, teremos uma exceção do tipo InvalidOperationException sendo disparada. Mas porque isso ocorre? Quando você invoca um serviço WCF a partir de um cliente qualquer, dentro do envelope SOAP temos a SoapAction. Essa informação determina o “alvo” da requisição, ou melhor, qual a operação que será disparada no serviço. Essa informação é uma junção entre as propriedades Namespace do atributo ServiceContractAttribute com a propriedade Name, exposta pelo atributo OperationContractAttribute. Quando essas configurações não são informadas, por padrão, ele define a propriedade Namespace para “http://tempuri.org/”, e com isso, a SoapAction final será: “http://tempuri.org/TeuContrato/TuaOperacao”.
Sendo assim, como temos Interfaces com o mesmo nome, e talvez até a mesma estrutura, elas terão em tempo de execução a mesma SoapAction. Com isso, o WCF não conseguirá entender para qual delas encaminhar a requisição, e neste caso antes de efetivamente abrir o host, irá disparar a exceção que falamos acima. Assim como os namespaces que utilizamos no VB.NET/C#, os namespaces do XML também servem para evitar conflitos de nomenclatura, como é o caso aqui. Configurando os contratos com os seus respectivos namespaces, evitaremos o problema. O código abaixo ilustra isso:
namespace Core
{
[ServiceContract(Namespace = "http://www.israelaece.com/Core")]
public interface IContrato
{
[OperationContract]
string Ping(string value);
}
}
namespace Tools
{
[ServiceContract(Namespace = "http://www.israelaece.com/Tools")]
public interface IContrato
{
[OperationContract]
string Ping(string value);
}
}
É importante não confundir o endereço do serviço com a SoapAction. O endereço do serviço é aquele que definimos durante a criação do endpoint, enquanto a SoapAction é o “alvo” da requisição. Convencionou-se utilizar uma URL na SoapAction, mas isso não é uma obrigação, ou seja, você poderia utilizar algo como “AppCore” e “AppTools” ao invés. Geralmente utiliza-se a URL quando o serviço está público, e o nome da aplicação se ele está acessível apenas internamente.
A partir do momento que você pode receber Interfaces criadas por outros membros do time, ou até mesmo por outras empresas, há a possibilidade de haver nomes de Interfaces e de membros iguais. Quando isso acontece, podemos utilizar um recurso fornecido pela própria linguagem, que é a implementação explícita da Interface, e os conflitos de nomenclatura não ocorrem.
Como essa classe trata-se de um serviço WCF, se utilizarmos esse recurso tudo compilará sem problemas, mas ao rodar o serviço, teremos uma exceção do tipo InvalidOperationException sendo disparada. Mas porque isso ocorre? Quando você invoca um serviço WCF a partir de um cliente qualquer, dentro do envelope SOAP temos a SoapAction. Essa informação determina o “alvo” da requisição, ou melhor, qual a operação que será disparada no serviço. Essa informação é uma junção entre as propriedades Namespace do atributo ServiceContractAttribute com a propriedade Name, exposta pelo atributo OperationContractAttribute. Quando essas configurações não são informadas, por padrão, ele define a propriedade Namespace para “http://tempuri.org/”, e com isso, a SoapAction final será: “http://tempuri.org/TeuContrato/TuaOperacao”.
Sendo assim, como temos Interfaces com o mesmo nome, e talvez até a mesma estrutura, elas terão em tempo de execução a mesma SoapAction. Com isso, o WCF não conseguirá entender para qual delas encaminhar a requisição, e neste caso antes de efetivamente abrir o host, irá disparar a exceção que falamos acima. Assim como os namespaces que utilizamos no VB.NET/C#, os namespaces do XML também servem para evitar conflitos de nomenclatura, como é o caso aqui. Configurando os contratos com os seus respectivos namespaces, evitaremos o problema. O código abaixo ilustra isso:
namespace Core
{
[ServiceContract(Namespace = "http://www.israelaece.com/Core")]
public interface IContrato
{
[OperationContract]
string Ping(string value);
}
}
namespace Tools
{
[ServiceContract(Namespace = "http://www.israelaece.com/Tools")]
public interface IContrato
{
[OperationContract]
string Ping(string value);
}
}
É importante não confundir o endereço do serviço com a SoapAction. O endereço do serviço é aquele que definimos durante a criação do endpoint, enquanto a SoapAction é o “alvo” da requisição. Convencionou-se utilizar uma URL na SoapAction, mas isso não é uma obrigação, ou seja, você poderia utilizar algo como “AppCore” e “AppTools” ao invés. Geralmente utiliza-se a URL quando o serviço está público, e o nome da aplicação se ele está acessível apenas internamente.
- WCF – Gerenciamento de InstânciaWCF
- Gerando Gráficos com Silverlight, WCF e LINQSilverlight
- Criando e consumindo serviços com WCFWCF
- Usando Timer no WPF e SilverlightSilverlight
- Utilizando WCF-Provided HostWCF/WPF