Atualização em Agosto de 2020: Esse post é antigo, foi escrito em 2012. Tal conteúdo não é mais aplicável nos tempos de hoje. Quer verificar a disponibilidade de um API, qualquer tipo? Ate mesmo Back-end Services? Crie um Health Check e configure alertas caso nao esteja disponivel.


Olá Pessoal!

Hoje eu quero escrever um Post útil, de uma tarefa que tive que fazer aqui na empresa. Ela consiste de criar uma página para verificar todos os serviços que estão disponíveis dos nossos Sistemas de forma centralizada. A partir de todos os endereços dados.

Ou seja eu me deparei com o seguinte problema:

Como verificar a Disponibilidade de um Serviço WCF ou WebService de forma genérica, passando por parâmetro apenas o EndPoint ou o Endereço do WebService que é uma URL.

Antes de mostrar o meu código, darei uma breve explicação sobre ele, dividido em duas partes: WebService e WCF.

Validando um WebService:

O Web Service é relativamente fácil. Considerando que ele é uma URL. E quando você adiciona referência de um Web Service, onde o Visual Studio constrói suas classes de Proxys? Pelo WSDL é claro! Quando você dá Add Web Reference no Project ele busca esse endereço e mostra para você todos os dados daquele Web Service. Até ai estou ensinando padre à rezar, isso é claro para todos que desejam implementar o código desse Post =D

Considerando que o WSDL é um XML, o que precisariamos fazer é: Criar um método dado uma string como parâmetro, adicionar a QueryString “?wsdl” e verificar se a saida é um XML. Simples assim, foi exatamente o que eu fiz. Obviamente precisamos validar Exceptions como por exemplo TimeOut “Se o serviço estiver fora, talvez tenhamos esse resultado como resposta =D”

Só uma observação: O Servidor Web pode retornar por exemplo “Service Busy” ou “Forbidden” ou qualquer outra saída de HTTP Code, diferente do Sucess “2xx”.

 
Validando um WCF:

Aqui o negócio fica mais difícil. Pensei em várias formas de fazer e também realizei várias pesquisas. Como o WCF o Binding dele não é necessariamente HTTP, podendo ser wsHttpBinding, netMsmqBinding, netNamedPipeBinding… Etc. Então teríamos que validar o serviço de fato.

Alguns programadores me sugeriram:

  • Dar um ping no servidor “Acho que não preciso explicar porque descartei isso né? ;)”
  • Adicionar um serviço do Tipo HelloWorld em todos “Fucionaria, porém eu não posso alterar milhões de serviços que já estão em produção :(“
  • Tem também uma terceira opção que parece ser do Próprio Framework, mas não temos referências boas na internet. Então nem implementei.

  Depois eu comecei a pensar e você também pensará comigo: Se o WebService quando eu faço Add Web Reference ele busca o WSDL para construir o Proxy. Como é feito o Add Service Reference do WCF? Era exatamente esse ponto que eu consegui resolver! O Meu amigo o Arquiteto de Software Rafael Tolotti “http://rafatolotti.wordpress.com/”   Me disse o seguinte: Por default quando você cria um serviço WCF ele essas chaves no WebConfig: Esse EndPoint: <endpoint address=”mex” binding=”mexHttpBinding” contract=”IMetadataExchange” /> E esse Behavior: Que por sua vez depende da chave: <serviceMetadata httpGetEnabled=”true” /> E pra que serve essas chaves? Para justamente quando você tiver um serviço diferente de HTTP que não tenha a saida do WSDL por default, o WCF cria-la! Assim quando você der o Add Service Reference ele procurara esse endereço e achará o WSDL. Por exemplo, esse endereço de Serviço: net.tcp://meuservidor.com.br/ServicoPedido/Pedidos.svc O WSDL dele seria: http://meuservidor.com.br/ServicoPedido/Pedidos.svc?wsdl   Se você tiver com aquele Behavior e o EndPoint criados, ele funcionará. Obviamente você terá que ver se a configuração está certa do seu servidor, para ver se está funcionando. Se for o IIS do Visual Studio funcionará !   Ou seja, antes de você criar o endereço para verificar, basta mudar o net.tcp para http. E pronto.

Segue o Código:

public class CheckService {
  private string _endereco;
  public String Endereco {
    get {
      return _endereco;
    }
    set {
      _endereco = value;
    }
  }

  private string _descricao;
  public string Descricao {
    get {
      return _descricao;
    }
    set {
      _descricao = value;
    }
  }

  private string _erro;
  public string Erro {
    get {
      return _erro;
    }
    set {
      _erro = value;
    }
  }
}

public void PreencherStatusServico(POCO.CheckService oCheckService) {
  string strRequestWSDL;

  HttpWebRequest request = (HttpWebRequest) WebRequest.Create(oCheckService.Endereco);

  request.Timeout = 5000;
  try
  {
    WebResponse oWebResponse = request.GetResponse();
    strRequestWSDL = oCheckService.Endereco + "?wsdl";
    oWebResponse = WebRequest.Create(strRequestWSDL).GetResponse();
    if (!oWebResponse.ContentType.ToUpper() == "TEXT/XML; CHARSET=UTF-8")

    {
      oCheckService.Erro = "Erro: Não é xml válido.";
    }
  }
  catch(TimeoutException ex)
  {
    oCheckService.Erro = "Erro de TimeOut: " + ex.Message;
    if (ex.InnerException != null &amp; amp; &amp; amp; ex.InnerException.Message != null)

    {
      oCheckService.Erro += "<br /&gt;Inner Exception: " + ex.InnerException.Message;
    }
  }
  catch(Exception ex)
  {
    oCheckService.Erro = "Erro: " + ex.Message;
    if (ex.InnerException != null &amp; amp; &amp; amp; ex.InnerException.Message != null)
    {
      oCheckService.Erro += "<br /&gt;Inner Exception: " + ex.InnerException.Message;
    }
  }
}

É isso ai Pessoal, qualquer dúvida é só deixar um comentário.

Abraços!