Início rápido de solução de problemas do WCF

Este tópico lista uma série de problemas conhecidos que os clientes tiveram ao desenvolver clientes e serviços do WCF. Se o problema que você está enfrentando não estiver nesta lista, recomendamos que configure o rastreamento para seu serviço. Isso gerará um arquivo de rastreamento que você poderá exibir com o visualizador de arquivos de rastreamento e obterá informações detalhadas sobre exceções que podem estar ocorrendo dentro do serviço. Para obter mais informações sobre como configurar o rastreamento, consulte: Configurando o Rastreamento. Para obter mais informações sobre o visualizador de arquivos de rastreamento, consulte: Service Trace Viewer Tool (SvcTraceViewer.exe).

  1. Depois de instalar o Windows 7 e o IIS, quando tento navegar até um serviço WCF, recebo a seguinte mensagem de erro: Erro HTTP 404.3 – Não encontrado

    Erro HTTP 404.3 – Não EncontradoA página que você está solicitando não pode ser atendida devido à configuração da extensão. Se a página for um script, adicione um manipulador. Se o arquivo deve ser baixado, adicione um mapa MIME. Informações detalhadas de erroModule StaticFileModule.

  2. Às vezes, recebo uma MessageSecurityException na segunda solicitação se meu cliente ficar ocioso por um tempo após a primeira solicitação. O que está acontecendo?

  3. Meu serviço começa a rejeitar novos clientes depois que cerca de 10 clientes estão interagindo com ele. O que está acontecendo?

  4. Posso carregar minha configuração de serviço de algum lugar diferente do arquivo de configuração do aplicativo WCF?

  5. Meu serviço e meu cliente funcionam muito bem, mas não consigo fazê-los trabalhar quando o cliente está em outro computador? O que está acontecendo?

  6. Quando lancei uma Exceção <FaultException>em que o tipo é uma exceção, sempre recebo um tipo de FaultException geral no cliente e não no tipo genérico. O que está acontecendo?

  7. Parece que as operações unidirecionais e de solicitação-resposta retornam aproximadamente na mesma velocidade quando a resposta não contém dados. O que está acontecendo?

  8. Estou usando um certificado X.509 com meu serviço e recebo um System.Security.Cryptography.CryptographicException. O que está acontecendo?

  9. Alterei o primeiro parâmetro de uma operação de maiúsculas para minúsculas; agora meu cliente lança uma exceção. O que está acontecendo?

  10. Estou usando uma das minhas ferramentas de rastreamento e recebo um EndpointNotFoundException. O que está acontecendo?

  11. Ao chamar um aplicativo HTTP Web do WCF de um aplicativo SOAP WCF, o serviço retorna o seguinte erro: Método 405 Não Permitido

O que é o endereço base? Como ele se relaciona com um endereço de ponto de extremidade?

Depois de instalar o Windows 7 e o IIS, quando tento navegar até um serviço WCF, recebo a seguinte mensagem de erro: Erro HTTP 404.3 – Não encontrado

A mensagem de erro completa é:

Erro HTTP 404.3 – Não EncontradoA página que você está solicitando não pode ser atendida devido à configuração da extensão. Se a página for um script, adicione um manipulador. Se o arquivo deve ser baixado, adicione um mapa MIME. Informações detalhadas de erroModule StaticFileModule.

Essa mensagem de erro ocorre quando "Ativação HTTP do Windows Communication Foundation" não é explicitamente definida no Painel de Controle. Para definir isso, vá para o Painel de Controle, clique em Programas no canto inferior esquerdo da janela. Clique em Ativar ou desativar os recursos do Windows. Expanda o Microsoft .NET Framework 3.5.1 e selecione a Ativação HTTP do Windows Communication Foundation.

Às vezes, recebo uma MessageSecurityException na segunda solicitação se meu cliente ficar ocioso por um tempo após a primeira solicitação. O que está acontecendo?

A segunda solicitação pode falhar principalmente por dois motivos: (1) a sessão atingiu o tempo limite ou (2) o servidor Web que está hospedando o serviço é reciclado. No primeiro caso, a sessão é válida até o tempo limite do serviço. Quando o serviço não recebe uma solicitação do cliente dentro do período de tempo especificado na associação do serviço (ReceiveTimeout), o serviço encerra a sessão de segurança. Mensagens de cliente subsequentes resultam no MessageSecurityException. O cliente deve restabelecer uma sessão segura com o serviço para enviar mensagens futuras ou usar um token de contexto de segurança com estado. Tokens de contexto de segurança com estado também permitem que uma sessão segura sobreviva a um servidor Web sendo reciclado. Para obter mais informações sobre como usar tokens de contexto seguro com estado em uma sessão segura, consulte Como criar um token de contexto de segurança para uma sessão segura. Como alternativa, você pode desabilitar sessões seguras. Ao usar a associação <wsHttpBinding>, você pode definir a propriedade establishSecurityContext para false, para desabilitar sessões seguras. Para desabilitar sessões seguras para outras associações, você deve criar uma associação personalizada. Para obter detalhes sobre como criar uma associação personalizada, consulte Como criar uma associação personalizada usando o SecurityBindingElement. Antes de aplicar qualquer uma dessas opções, você deve entender os requisitos de segurança do aplicativo.

Meu serviço começa a rejeitar novos clientes depois que cerca de 10 clientes estão interagindo com ele. O que está acontecendo?

Por padrão, os serviços podem ter apenas 10 sessões simultâneas. Portanto, se as associações de serviço usarem sessões, o serviço aceitará novas conexões de cliente até atingir esse número, após o qual recusará novas conexões de cliente até que uma das sessões atuais termine. Você pode dar suporte a mais clientes de várias maneiras. Se o serviço não exigir sessões, não use uma associação com sessão. (Para obter mais informações, consulte Usando Sessões.) Outra opção é aumentar o limite de sessão alterando o valor da MaxConcurrentSessions propriedade para o número apropriado para sua circunstância.

Posso carregar minha configuração de serviço de algum lugar diferente do arquivo de configuração do aplicativo WCF?

No entanto, é necessário criar uma classe ServiceHost personalizada que substitua o método ApplyConfiguration. Dentro desse método, você pode chamar a configuração base para carregar primeiro (se quiser carregar as informações de configuração padrão também), mas também pode substituir totalmente o sistema de carregamento de configuração. Se quiser carregar a configuração de um arquivo de configuração diferente do arquivo de configuração do aplicativo, analise o arquivo de configuração por conta própria e carregue a configuração.

O exemplo de código a seguir mostra como substituir o método ApplyConfiguration e configurar diretamente um ponto de extremidade.

public class MyServiceHost : ServiceHost  
{  
    public MyServiceHost(Type serviceType, params Uri[] baseAddresses)
      : base(serviceType, baseAddresses)  
    {
        Console.WriteLine("MyServiceHost Constructor");
    }  
  
    protected override void ApplyConfiguration()  
    {  
        string straddress = GetAddress();  
        Uri address = new Uri(straddress);  
        Binding binding = GetBinding();  
        base.AddServiceEndpoint(typeof(IData), binding, address);  
    }  
  
    string GetAddress()  
    {
        return "http://MyMachine:7777/MyEndpointAddress/";
    }  
  
    Binding GetBinding()  
    {  
        WSHttpBinding binding = new WSHttpBinding();  
        binding.Security.Mode = SecurityMode.None;  
        return binding;  
    }  
}  

Meu serviço e meu cliente funcionam muito bem, mas não consigo fazê-los trabalhar quando o cliente está em outro computador? O que está acontecendo?

Dependendo da exceção, pode haver vários problemas:

  • Talvez seja necessário alterar os endereços do ponto de extremidade do cliente para o nome do host e não para "localhost".

  • Talvez seja necessário abrir a porta para o aplicativo. Para obter detalhes, consulte Instruções de firewall dos exemplos do SDK.

  • Para outros problemas possíveis, consulte o tópico de exemplos Executando os exemplos do Windows Communication Foundation.

  • Se o cliente estiver usando credenciais do Windows e a exceção for um SecurityNegotiationException, configure o Kerberos da seguinte maneira.

    1. Adicione as credenciais de identidade ao elemento de ponto de extremidade no arquivo App.config do cliente:

      <endpoint
        address="http://MyServer:8000/MyService/"
        binding="wsHttpBinding"
        bindingConfiguration="WSHttpBinding_IServiceExample"
        contract="IServiceExample"
        behaviorConfiguration="ClientCredBehavior"
        name="WSHttpBinding_IServiceExample">  
        <identity>  
          <userPrincipalName value="name@corp.contoso.com"/>  
        </identity>  
      </endpoint>  
      
    2. Execute o serviço auto-hospedado na conta System ou NetworkService. Você pode executar este comando para criar uma janela de comando na conta do sistema:

      at 12:36 /interactive "cmd.exe"  
      
    3. Hospede o serviço nos Serviços de Informações da Internet (IIS), que, por padrão, usa a conta SPN (nome da entidade de serviço).

    4. Registre um novo SPN com o domínio usando SetSPN. Você precisa ser um administrador de domínio para fazer isso.

Para obter mais informações sobre o protocolo Kerberos, consulte Os Conceitos de Segurança Usados no WCF e:

Quando lancei uma Exceção <FaultException>em que o tipo é uma exceção, sempre recebo um tipo de FaultException geral no cliente e não no tipo genérico. O que está acontecendo?

É altamente recomendável que você crie seu próprio tipo de dados de erro personalizado e declare isso como o tipo de detalhe em seu contrato de falha. O motivo é que usar os tipos de exceção fornecidos pelo sistema:

  • Cria uma dependência de tipo que remove um dos maiores pontos fortes dos aplicativos orientados ao serviço.

  • Não pode depender de exceções serializando de maneira padrão. Alguns, como SecurityException, podem não ser serializáveis em tudo.

  • Expõe detalhes da implementação interna aos clientes. Para obter mais informações, consulte Especificando e tratando falhas em contratos e serviços.

No entanto, caso você esteja depurando um aplicativo, poderá serializar informações de exceção e devolvê-la ao cliente usando a classe ServiceDebugBehavior.

Parece que as operações unidirecionais e de solicitação-resposta retornam aproximadamente na mesma velocidade quando a resposta não contém dados. O que está acontecendo?

Especificar que uma operação é de uma maneira significa apenas que o contrato de operação aceita uma mensagem de entrada e não retorna uma mensagem de saída. No WCF, todas as invocações de cliente retornam quando os dados de saída foram gravados no fio ou uma exceção é gerada. As operações unidirecionais funcionam da mesma maneira e podem ser geradas se o serviço não puder ser localizado ou bloqueado se o serviço não estiver preparado para aceitar os dados da rede. Normalmente no WCF, isso resulta em chamadas unidirecionais retornando ao cliente mais rapidamente do que solicitação-resposta; mas qualquer condição que reduza o envio dos dados de saída pela rede reduz as operações unidirecionais, bem como as operações de solicitação-resposta. Para obter mais informações, consulte Serviços unidirecionais e Acessando serviços usando um cliente WCF.

Estou usando um certificado X.509 com meu serviço e recebo um System.Security.Cryptography.CryptographicException. O que está acontecendo?

Isso geralmente ocorre depois de alterar a conta de usuário na qual o processo de trabalho do IIS é executado. Por exemplo, no Windows XP, se você alterar a conta de usuário padrão em que o Aspnet_wp.exe é executado de ASPNET para uma conta de usuário personalizada, você poderá ver esse erro. Se estiver usando uma chave privada, o processo que a usa precisará ter permissões para acessar o arquivo que armazena essa chave.

Se esse for o caso, você deverá conceder privilégios de acesso de leitura à conta do processo para o arquivo que contém a chave privada. Por exemplo, se o processo de trabalho do IIS estiver em execução na conta do Bob, você precisará dar a Bob acesso de leitura ao arquivo que contém a chave privada.

Para obter mais informações sobre como dar à conta de usuário correta acesso ao arquivo que contém a chave privada de um certificado X.509 específico, consulte Como tornar os certificados X.509 acessíveis ao WCF.

Alterei o primeiro parâmetro de uma operação de maiúsculas para minúsculas; agora meu cliente lança uma exceção. O que está acontecendo?

Os valores dos nomes de parâmetro na assinatura de operação fazem parte do contrato e diferenciam maiúsculas de minúsculas. Use o atributo System.ServiceModel.MessageParameterAttribute quando precisar distinguir entre o nome do parâmetro local e os metadados que descrevem a operação para aplicativos cliente.

Estou usando uma das minhas ferramentas de rastreamento e recebo um EndpointNotFoundException. O que está acontecendo?

Se você estiver usando uma ferramenta de rastreamento que não seja o mecanismo de rastreamento WCF fornecido pelo sistema e receber um EndpointNotFoundException que indique que houve uma incompatibilidade de filtro de endereço, você precisará usar a classe ClientViaBehavior para direcionar as mensagens para o utilitário de rastreamento e fazer com que o utilitário redirecione essas mensagens para o endereço do serviço. A classe ClientViaBehavior altera o cabeçalho de endereçamento Via para especificar o próximo endereço de rede separadamente do destinatário final, indicado pelo cabeçalho de endereçamento To. No entanto, ao fazer isso, não altere o endereço do ponto de extremidade, que é usado para estabelecer o valor de To.

O exemplo de código a seguir mostra um exemplo de arquivo de configuração cliente.

<endpoint
  address="http://localhost:8000/MyServer/"  
  binding="wsHttpBinding"  
  bindingConfiguration="WSHttpBinding_IMyContract"  
  behaviorConfiguration="MyClient"
  contract="IMyContract"
  name="WSHttpBinding_IMyContract">  
</endpoint>  
<behaviors>  
  <endpointBehaviors>  
    <behavior name="MyClient">  
      <clientVia viaUri="http://localhost:8001/MyServer/"/>  
    </behavior>  
  </endpointBehaviors>  
</behaviors>  

O que é o endereço base? Como ele se relaciona com um endereço de ponto de extremidade?

Um endereço base é o endereço raiz de uma classe ServiceHost. Por padrão, se você adicionar uma classe ServiceMetadataBehavior à configuração de serviço, a WSDL (Linguagem de Descrição dos Serviços Web) para todos os pontos de extremidade que o host publica serão recuperados do endereço base HTTP, além de qualquer endereço relativo fornecido ao comportamento dos metadados, além de "?wsdl". Se você estiver familiarizado com ASP.NET e IIS, o endereço base será equivalente ao diretório virtual.

Compartilhar uma porta entre um ponto de extremidade de serviço e um ponto de extremidade mex usando o NetTcpBinding

Se você especificar o endereço base de um serviço como net.tcp://MyServer:8080/MyService e adicionar os seguintes pontos de extremidade:

<services>  
  <service name="Microsoft.Samples.NetTcp.CalculatorService">  
    <endpoint address="calcsvc" binding ="netTcpBinding" contract="Microsoft.Samples.NetTcp.ICalculator"/>  
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />  
  </service>  
</services>  

E se você modificar uma das configurações do NetTcpBinding, conforme mostrado no seguinte snippet de configuração:

<bindings>  
  <netTcpBinding>  
    <binding closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="11" maxReceivedMessageSize="65536">  
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>  
      <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>  
      <security mode="Transport">  
        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/>  
      </security>  
    </binding>  
  </netTcpBinding>  
</bindings>  

Você verá um erro como o seguinte: Exceção Sem Tratamento: System.ServiceModel.AddressAlreadyInUseException: já existe um ouvinte no ponto de extremidade IP 0.0.0.0:9000 Você pode contornar esse erro especificando uma URL totalmente qualificada com uma porta diferente para o ponto de extremidade MEX, conforme mostrado no seguinte snippet de configuração:

<services>  
  <service name="Microsoft.Samples.NetTcp.CalculatorService">  
    <endpoint address="calcsvc" binding ="netTcpBinding" contract="Microsoft.Samples.NetTcp.ICalculator"/>  
    <endpoint address="net.tcp://localhost:9001/servicemodelsamples/mex" binding="mexTcpBinding" contract="IMetadataExchange" />  
  </service>  
</services>  

Ao chamar um aplicativo HTTP Web do WCF de um aplicativo SOAP WCF, o serviço retorna o seguinte erro: Método 405 Não Permitido

Chamar um aplicativo HTTP da Web do WCF (um serviço que usa WebHttpBinding e WebHttpBehavior) de um serviço WCF pode gerar a seguinte exceção: Unhandled Exception: System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: The remote server returned an unexpected response: (405) Method Not Allowed. essa exceção ocorre porque o WCF substitui a saída OperationContext com a entrada OperationContext. Para resolver esse problema, crie uma OperationContextScope na operação de serviço HTTP da Web do WCF. Por exemplo:

public string Echo(string input)  
{  
    using (new OperationContextScope(this.InnerChannel))  
    {  
        return base.Channel.Echo(input);  
    }  
}  

Confira também