Introdução
SOAP (Simple Object Access Protocol) é um protocolo para a troca de informações estruturadas na implementação de serviços web, usando o XML Information Set como o seu formato de mensagem (source: https://en.wikipedia.org/wiki/SOAP). As mensagens podem passar por uma variedade de protocolos na camada de aplicação, por exemplo HTTP(s).
Neste artigo vamos ver como gerar código em C# a partir de um um ficheiro WSDL, importando esse ficheiro para o nosso projeto .NET Core, e ver alguns dos problemas comuns que por vezes surgem com esta funcionalidade.
Contexto
- SOAP
A especificação do SOAP define algo conhecido como uma "SOAP message" que é o que é enviado para o serviço web e à aplicação de cliente.
O diagrama da arquitetura SOAP ilustrado abaixo, mostra os vários blocos de construção de uma SOAP Message.
Para descrever as funcionalidades de um web service baseado em SOAP, é utilizada uma linguagem baseada em XML chamada WSDL (Web Services Description Language).
Para testar web services baseados em SOAP, são necessários ficheiros WSDL. A maioria das ferramentas usadas para testar web services SOAP, bem como projetos .NET Core, usa ficheiros WSDL para gerar pedidos de teste, afirmações e automação de testes (mock services)
. Ficheiros WSDL definem vários aspetos de SOAP messages:
- Se algum elemento ou atributo é permitido ser usado várias vezes
- Os elementos e atributos obrigatórios e/ou opcionais
- Uma ordem específica dos elementos, se necessário
- WCF
Windows Communication Foundation (WCF) é uma estrutura para a construção de aplicações orientadas a serviços. Com WCF, podemos enviar dados como mensagens assíncronas de um endpoint de um serviço para outro. Foi desenvolvido pela Microsoft e lançado com o .NET Framework 3.0, com o objetivo de unificar tecnologias existentes tais como: COM+, MSMQ-Message Queue, Enterprise Services, .NET Remoting e Web Services.
- .NET Core
.NET Core é uma framework de desenvolvimento web para a construção de aplicações web na plataforma .NET. Pode ser usado para desenvolver diferentes tipos de aplicações, tais como mobile, desktop, web, cloud, IoT, machine learning, microservices, jogos e assim por diante.
É uma framework open-source mantida pela Microsoft que pode correr em Windows, macOS ou Linux, cada um com um runtime diferente que executa o código e gera o mesmo output.
Implementação
Para este exemplo vamos primeiro configurar o nosso Visual Studio a fim de permitir que crie WCF Web Service References, e só então configurar o nosso projeto para usar um cliente para consumir o web service. Vamos utilizar um web service de teste que se encontra disponível em http://www.dneonline.com/calculator.asmx?wsdl para demonstrar a funcionalidade. Para simplificar veremos como implementar um cliente para operar no web service que será usado no nosso projecto .NET do tipo WEB API.
– Instalar Microsoft WCF Web Services Reference Provider no Visual Studio
Antes de qualquer outra coisa, temos que verificar se o Visual Studio tem a extensão para Microsoft WCF Web Service Reference Provider instalado. Em versões mais antigas do Visual Studio pode já estar instalado por defeito, mas nas versões mais recentes deve ser adicionada a extensão manualmente.
Para tal, temos que ir para o menu Tools -> Get Tools and Features... (ou diretamente no Visual Studio Installer) e procurar o componente individual “Windows Communication Foundation”, como exibido na imagem seguinte:
– Criar .NET Core WEB API project
Em seguida podemos criar um novo projeto. Vamos usar um template ASP.NET Core Web API para este exemplo.
Depois de criar o nosso projeto, teremos esta estrutura de pastas:
– Gerar código de referência a partir de um WSDL file
Clicando com o botão direito do rato em Connected Services visto na imagem anterior, teremos a opção de adicionar um novo connected service:
Se a extensão WCF está instalada corretamente, teremos a opção de adicionar um WCF Web Service Reference provider.
Ao fornecer o WDSL URI e clicando “Go”, obteremos uma lista de serviços que iremos utilizar para fazer referência a estes métodos no projeto, e um Namespace que irá recorrer para fazer referência aos métodos do projeto.
Ao clicar em "Next", iremos fazer algumas configurações, como por exemplo, os tipos de coleções que devem ser geradas. Vamos escolher System.Collections.Generic.List para o nosso exemplo.
Clicando novamente em "Next", veremos o último ecrã para a configuração do WCF Web Service Reference, que nos permite escolher se as classes geradas serão públcias ou privadas, e se queremos gerar métodos síncronos para além dos assíncronos, que já são gerados por defeito.
Clicando em "Finish" o scaffolding vai começar, e as nossas classes serão geradas.
– Utilizando Connected Service
Depois do processo estar concluído, teremos no nosso Solution Explorer o connected service disponível, com a nossa referência gerada, onde teremos os nossos endpoints e métodos configurados.
Visto termos escolhido gerar os métodos síncronos também, teremos vários métodos:
E também os endpoints:
Então, agora que temos uma ligação ao web service, podemos começar a usá-lo no nosso projeto. Vamos começar por criar um novo Controlador para demonstrar o uso do recém-criado connected service.
Começamos por adicionar à pasta Controllers um novo controlador chamado "Add”:
Em seguida, vamos criar um cliente para comunicar com o nosso connected service. Para isso, devemos fazer uma referência à nossa CalculatorReference, e indicar ao cliente qual o Endpoint a ser utilizado:
O cliente deve ser aberto antes da utilização, e fechado depois de receber os resultados, então vamos chamar o método "Add" do nosso web service para ver se podemos obter a soma entre o integer1 e integer2. Não esqueçer de tornar o método "Get" assíncrono:
Seguimos e fazemos o pedido para o nosso controlador, inserindo um valor para integer1 e integer2:
Como resultado, obtemos a soma dos dois números inteiros:
Funcionou! Podemos usar outros métodos do nosso web service, como multiplicar:
– Possíveis problemas
Às vezes podem ocorrer erros que são difíceis de resolver, então aqui estão alguns deles:
- Cada elemento filho tem a sua própria declaração de namespaces, em vez de herdar do pai ou do nó de root
Alguns web services não permitem que cada elemento no payload tenha os seus próprios namespaces, em vez de herdar do elemento pai.
<test:Parent xmlns:test="http://myschema.org">
<test:Child1 xmlns:test="http://myschema.org">Test1</test:Child1>
<test:Child2 xmlns:test="http://myschema.org">20</test:Child2>
</test:Parent>
Para resolver isto, devemos declarar que o pai é um element wrapper e um nó de root:
[System.ServiceModel.MessageContractAttribute(IsWrapped=true, WrapperName = "Parent", WrapperNamespace = "http://myschema.org")][System.Xml.Serialization.XmlRoot(Namespace = "http://myschema.org")]public partial class ParentWrapper{}
E assim, o XML será serializado:
<test:Parent xmlns:test="http://myschema.org"> <test:Child1>Test1</test:Child1> <test:Child2>20</test:Child2></test:Parent>
- Elementos atributos xsi:nil="true"
Por vezes os web services não permitem marcar valores nulos como xsi:nil=”true”, então, em vez disso, devemos remover estes elementos removendo o atributo “IsNullable=true” da declaração do XmlElement no código gerado. Em vez disto:
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
deverá ler-se:
[System.Xml.Serialization.XmlElementAttribute()]
Conclusão
Aprendemos como consumir web services a partir de um ficheiro WSDL, gerando código através do nosso .NET Core Project e também alguns dos problemas comuns que podem surgir após a geração do código.
É uma ferramenta indispensável que nos permite poupar tempo e que pode simplificar bastante o nosso trabalho, assim como manter o nosso projeto limpo e organizado.
#SOAP #WebServices #.NETCore