Condividi tramite


Guida rapida alla risoluzione dei problemi di WCF

In questo argomento viene elencata una serie di problemi noti rilevati dai clienti durante lo sviluppo di client e servizi WCF. Se il problema rilevato non presente in questo elenco, si consiglia di configurare la traccia del servizio. In tal modo verrà generato un file di traccia che è possibile visualizzare con il visualizzatore dei file di traccia e verranno ricevute informazioni dettagliate sulle eccezioni che si possono verificare nel servizio. Per ulteriori informazioni sulla configurazione della traccia, vedere Configurazione delle funzionalità di traccia. Per ulteriori informazioni sul visualizzatore dei file di traccia, vedere Strumento Visualizzatore di tracce dei servizi (SvcTraceViewer.exe).

  1. A volte viene restituita un'eccezione MessageSecurityException alla seconda richiesta se il client è inattivo per un periodo di tempo dopo la prima richiesta. Qual è il problema?

  2. Il servizio rifiuta nuovi client se sta interagendo già con 10 client. Qual è il problema?

  3. È possibile caricare la configurazione del servizio da una posizione diversa dal file di configurazione dell'applicazione WCF?

  4. Il servizio e il client funzionano correttamente, ma quando il client è in un altro computer non funzionano più. Qual è il problema?

  5. Quando si genera un'eccezione FaultException<Exception> in cui il tipo è un'eccezione, viene restituito sempre un tipo FaultException generale sul client e non il tipo generico. Qual è il problema?

  6. Sembra che le operazioni unidirezionali e request-reply vengano restituite approssimativamente alla stessa velocità quando la risposta non contiene dati. Qual è il problema?

  7. Utilizzando un certificato X.509 con il servizio viene generata un'eccezione System.Security.Cryptography.CryptographicException. Qual è il problema?

  8. In seguito alla modifica del primo parametro di un'operazione di passaggio da lettere maiuscole a lettere minuscole, il client genera un'eccezione. Qual è il problema?

  9. Utilizzando uno degli strumenti di traccia, viene generata un'eccezione EndpointNotFoundException. Qual è il problema?

What is the base address? How does it relate to an endpoint address?

A volte viene restituita un'eccezione MessageSecurityException alla seconda richiesta se il client è inattivo per un periodo di tempo dopo la prima richiesta. Qual è il problema?

La seconda richiesta può non riuscire principalmente per due ragioni: (1) la sessione è scaduta o (2) il server Web che sta ospitando il servizio è stato riciclato. Nel primo caso, la sessione è valida fino al timeout del servizio. Quando il servizio non riceve una richiesta dal client entro il periodo di tempo specificato nell'associazione del servizio (ReceiveTimeout), il servizio termina la sessione di sicurezza. I messaggi client successivi determinano l'eccezione MessageSecurityException. Il client deve ristabilire una sessione protetta con il servizio per inviare altri messaggi o utilizzare un token del contesto di sicurezza con stato. I token del contesto di sicurezza con stato consentono inoltre a una sessione protetta di restare attiva quando un server Web viene riciclato. Per ulteriori informazioni su utilizzo di token del contesto di sicurezza con stato in una sessione protetta, vedere Procedura: creare un token di contesto di sicurezza per una sessione sicura. In alternativa, è possibile disabilitare le sessioni protette. Quando si utilizza l'associazione <wsHttpBinding>, è possibile impostare la proprietà establishSecurityContext su false per disabilitare le sessioni protette. Per disabilitare le sessioni protette per altre associazioni, è necessario creare un'associazione personalizzata. Per informazioni dettagliate sulla creazione di un'associazione personalizzata, vedere Procedura: creare un'associazione personalizzata utilizzando SecurityBindingElement. Prima di applicare qualsiasi opzione, è necessario conoscere i requisiti di sicurezza dell'applicazione.

Il servizio rifiuta nuovi client se sta interagendo già con 10 client. Qual è il problema?

Per impostazione predefinita, i servizi possono gestire solo 10 sessioni simultanee. Pertanto, se le associazioni del servizio utilizzano sessioni, il servizio accetta nuove connessioni client fino a raggiungere quel numero e in seguito rifiuta le nuove connessioni client fino a quando una delle sessioni correnti non viene chiusa. È possibile supportare più client in vari modi. Se il servizio non richiede le sessioni, non utilizzare un'associazione con sessione. (Per ulteriori informazioni, vedere Utilizzo di sessioni.) Un'altra opzione consiste nell'incrementare il limite di sessioni impostando il valore della proprietà MaxConcurrentSessions sul numero adatto alla circostanza.

È possibile caricare la configurazione del servizio da una posizione diversa dal file di configurazione dell'applicazione WCF?

È possibile, tuttavia è necessario creare una classe ServiceHost personalizzata che esegue l'override del metodo ApplyConfiguration. All'interno di tale metodo è possibile chiamare la base per caricare la prima configurazione (se si desidera caricare anche le informazioni di configurazione standard), ma si può anche sostituire completamente il sistema di caricamento della configurazione. Si noti che se si desidera caricare la configurazione da un file di configurazione diverso dal quello dell'applicazione, è necessario analizzare direttamente il file di configurazione e caricare la configurazione.

Nell'esempio di codice seguente viene illustrato come eseguire l'override del metodo ApplyConfiguration e configurare direttamente un endpoint.

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;
  }
}

Il servizio e il client funzionano correttamente, ma quando il client è in un altro computer non funzionano più. Qual è il problema?

In base all'eccezione, i problemi possono essere diversi:

  • Potrebbe essere necessario modificare gli indirizzi dell'endpoint del client sul nome host anziché su "localhost".

  • Potrebbe essere necessario aprire la porta all'applicazione. Per informazioni dettagliate, vedere Istruzioni del firewall negli esempi SDK.

  • Per altri possibili problemi, vedere l'argomento degli esempi Running the Samples in a Workgroup and Across Machines.

  • Se il client sta utilizzando le credenziali di Windows e l'eccezione è SecurityNegotiationException, configurare Kerberos come descritto di seguito.

    1. Aggiungere le credenziali di identificazione all'elemento dell'endpoint nel file App.config del client:

      <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. Eseguire il servizio indipendente con l'account System o NetworkService. È possibile eseguire questo comando per creare una finestra di comando con l'account System:

      at 12:36  /interactive "cmd.exe"
      
    3. Ospitare il servizio in Internet Information Services (IIS) che, per impostazione predefinita, utilizza l'account del nome dell'entità servizio (SPN).

    4. Registrare un nuovo SPN nel dominio utilizzando SetSPN. Si noti che è necessario essere un amministratore di dominio per poter eseguire questa operazione.

Per ulteriori informazioni su protocollo Kerberos, vedere Concetti relativi alla sicurezza utilizzati in WCF e:

Quando si genera un'eccezione FaultException<Exception> in cui il tipo è un'eccezione, viene restituito sempre un tipo FaultException generale sul client e non il tipo generico. Qual è il problema?

È consigliabile creare un tipo di dati dell'errore personalizzato e dichiararlo come tipo di dettaglio nel contratto di errore. Ciò è necessario in quanto, se si utilizzano tipi di eccezione forniti dal sistema:

  • Viene creata una dipendenza dal tipo che rimuove uno dei maggiori punti di forza delle applicazioni orientate ai servizi.

  • Non è possibile dipendere dalla serializzazione delle eccezioni in modo standard. Alcuni casi, come SecurityException, potrebbero non essere affatto serializzabili.

  • Vengono esposti dettagli di implementazione interni ai client. Per ulteriori informazioni, vedere Specifica e gestione di errori in contratti e servizi.

Se si sta eseguendo il debug di un'applicazione, tuttavia, è possibile serializzare le informazioni sull'eccezione e restituirle al client utilizzando la classe ServiceDebugBehavior.

Sembra che le operazioni unidirezionali e request-reply vengano restituite approssimativamente alla stessa velocità quando la risposta non contiene dati. Qual è il problema?

Per operazione unidirezionale si intende che il contratto dell'operazione accetta un messaggio di input e non restituisce un messaggio di output. In WCF, tutte le chiamate del client vengono restituite quando i dati in uscita sono stati scritti nella rete oppure viene generata un'eccezione. Le operazioni unidirezionali funzionano nello stesso modo e possono generare un'eccezione se il servizio non viene trovato o possono bloccarsi se il servizio non è pronto ad accettare i dati dalla rete. In genere in WCF ciò comporta che le chiamate unidirezionali vengono restituite al client più rapidamente delle operazioni request-reply; ma qualsiasi condizione che rallenta l'invio dei dati in uscita sulla rete rallenta anche le operazioni unidirezionali e le operazioni request-reply. Per ulteriori informazioni, vedere One-Way Services e Accesso ai servizi tramite client.

Utilizzando un certificato X.509 con il servizio viene generata un'eccezione System.Security.Cryptography.CryptographicException. Qual è il problema?

Questa situazione in genere si verifica dopo aver modificato l'account utente utilizzato per eseguire il processo di lavoro IIS. Ad esempio, in Windows XP, se si modifica l'account utente predefinito con cui si esegue Aspnet_wp.exe da ASPNET in un account utente personalizzato, è possibile che si verifichi questo errore. Se si utilizza una chiave privata, il processo che la utilizza dovrà disporre delle autorizzazioni per accedere al file in cui è archiviata tale chiave.

In questo caso, è necessario assegnare i privilegi di accesso in lettura all'account del processo per il file che contiene la chiave privata. Ad esempio, se il processo di lavoro IIS è in esecuzione con l'account Bob, è necessario assegnare a Bob l'accesso in lettura al file che contiene la chiave privata.

Per ulteriori informazioni su come assegnare all'account utente corretto l'accesso al file che contiene la chiave privata per un certificato X.509 specifico, vedere Procedura: rendere accessibili a WCF i certificati X.509.

In seguito alla modifica del primo parametro di un'operazione di passaggio da lettere maiuscole a lettere minuscole, il client genera un'eccezione. Qual è il problema?

Il valore dei nomi di parametro nella firma dell'operazione fa parte del contratto e supporta la distinzione tra maiuscole e minuscole. Utilizzare l'attributo System.ServiceModel.MessageParameterAttribute quando è necessario distinguere tra il nome del parametro locale e i metadati che descrivono l'operazione per le applicazioni client.

Utilizzando uno degli strumenti di traccia, viene generata un'eccezione EndpointNotFoundException. Qual è il problema?

Se si sta utilizzando uno strumento di traccia diverso dal meccanismo di traccia WCF fornito dal sistema e si riceve un'eccezione EndpointNotFoundException che indica una mancata corrispondenza del filtro di indirizzi, è necessario utilizzare la classe ClientViaBehavior per indirizzare i messaggi all'utilità di traccia e fare in modo che l'utilità reindirizzi tali messaggi all'indirizzo del servizio. La classe ClientViaBehavior modifica l'intestazione di indirizzamento Via per specificare il successivo indirizzo di rete separatamente dal destinatario finale, indicato dall'intestazione di indirizzamento To. Durante questa modifica è importante tuttavia non modificare l'indirizzo dell'endpoint che viene utilizzato per stabilire il valore To.

Nell'esempio di codice seguente viene illustrato un file di configurazione client di esempio.

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

Quale è l'indirizzo di base? In che modo è correlato a un indirizzo dell'endpoint?

Un indirizzo di base è l'indirizzo radice per una classe ServiceHost. Per impostazione predefinita, se si aggiunge una classe ServiceMetadataBehavior alla configurazione del servizio, il linguaggio di descrizione dei servizi Web (WSDL, Web Services Description Language) per tutti gli endpoint che l'host pubblica viene recuperato dall'indirizzo di base HTTP, oltre che da qualsiasi indirizzo relativo fornito al comportamento dei metadati, più "?wsdl". Se si ha familiarità con ASP.NET e IIS, l'indirizzo di base è equivalente alla directory virtuale.

Condivisione di una porta tra un endpoint servizio e un endpoint MEX utilizzando NetTcpBinding

Se si specifica l'indirizzo di base per un servizio come net.tcp://MioServer:8080/MioServizio e si aggiungono gli endpoint seguenti:

<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>

Se inoltre si modifica una delle impostazioni NetTcpBinding come illustrato nel frammento di configurazione seguente:

<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>

Verrà visualizzato un errore analogo al seguente: Eccezione non gestita: System.ServiceModel.AddressAlreadyInUseException: Esiste già un listener nell'endpoint IP 0.0.0.0:9000. Per risolvere il problema, specificare un URL completo con una porta diversa per l'endpoint MEX come illustrato nel frammento di configurazione seguente:

<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>

Vedere anche

Concetti

Debug degli errori di autenticazione di Windows