2009-12-03 14 views
6

Come garantire che la WCF ChannelFactory utilizza le impostazioni obbligatorio in configurazione XML (MaxArrayLength viene ignorato)Come garantire che la WCF ChannelFactory utilizza le impostazioni obbligatorio in configurazione XML (MaxArrayLength viene ignorato)

Ciao, Sono nuovo di Wcf e scrivendo il mio primo servizio e client Wcf. Preferisco non usare gli strumenti per generare la configurazione; Preferirei scrivere la configurazione personalmente. Il problema che sto cercando di risolvere è di un client che comunica con un servizio su netTcp. Il servizio può potenzialmente restituire payload molto grandi (più grande del default readerQuotas.maxArrayLength). I componenti che ho inizialmente sviluppato funzionano bene quando i payload del flusso di byte dello byte sono relativamente bassi (ovvero inferiori al valore predefinito che si pensa sia di circa 16 K). Posso risolvere questo problema programmaticamente creando un binding e impostando MaxArrayLength su un valore sufficientemente grande. Tuttavia, devo essere in grado di eseguire l'equivalente nella configurazione xxml.

mio app.config (client) è:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.serviceModel> 

     <client> 
      <endpoint address="net.tcp://localhost:9000/WcfDataService/RemoteDataRequesterService/" 
       binding="netTcpBinding" bindingConfiguration="unsecureNetTcpBinding" 
       contract="WcfDataServiceLib.IRemoteDataRequester" 
       name="DataRequesterEndpoint" /> 
     </client> 

     <bindings> 
      <netTcpBinding> 
       <binding name="unsecureNetTcpBinding" maxReceivedMessageSize="2147483647"> 
        <readerQuotas maxArrayLength="1000000" /> 
        <security mode="None" /> 
       </binding> 
      </netTcpBinding> 
     </bindings> 

    </system.serviceModel> 
</configuration> 

Il codice per creare il proxy client è la seguente:

private void Init() 
{ 
    var address = new EndpointAddress(@"net.tcp://localhost:9000/WcfDataService/RemoteDataRequesterService/"); 
    const string endpointName = "DataRequesterEndpoint"; 

    ChannelFactory<IRemoteDataRequester> factory = new ChannelFactory<IRemoteDataRequester>(
     endpointName); 

    IRemoteDataRequester proxy = factory.CreateChannel(address); 

    // call business methods on proxy ... 
} 

Nota che il codice è legato alla configurazione dalla variabile 'endpointname'.

lato servizio di configurazione (non credo che questo è rilevante, ma incluso per completezza):

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.serviceModel> 
     <services> 
      <service name="WcfDataServiceLib.RemoteDataRequesterService" behaviorConfiguration="WcfDataServiceLib.RemoteDataRequesterServiceBehavior"> 
       <host> 
        <baseAddresses> 
         <add baseAddress = "net.tcp://localhost:9000/WcfDataService/RemoteDataRequesterService" /> 
         <add baseAddress="http://localhost:8731/Design_Time_Addresses/WcfDataService/RemoteDataRequesterService/"/> 
        </baseAddresses> 
       </host> 
       <endpoint address ="" binding="netTcpBinding" bindingConfiguration="netTcpBindingConfig" contract="WcfDataServiceLib.IRemoteDataRequester"> 
        <identity> 
         <dns value="localhost"/> 
        </identity> 
       </endpoint> 
       <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 

      </service> 
     </services> 
     <behaviors> 
      <serviceBehaviors> 
       <behavior name="WcfDataServiceLib.RemoteDataRequesterServiceBehavior"> 
        <serviceMetadata httpGetEnabled="False"/> 
        <serviceDebug includeExceptionDetailInFaults="True" /> 
       </behavior> 
      </serviceBehaviors> 
     </behaviors> 

     <bindings> 
      <netTcpBinding> 
       <binding name="netTcpBindingConfig" receiveTimeout="00:00:30"> 
        <readerQuotas maxArrayLength="1000000"/> 
       </binding> 
       <binding name="netTcpReliableSession" receiveTimeout="00:00:30" > 
        <reliableSession enabled="true"/> 
       </binding> 
      </netTcpBinding> 
     </bindings> 

    </system.serviceModel> 
</configuration> 

Quando eseguo il cliente in uno scenario in cui un flusso di byte di grandi dimensioni è restituito dal servizio, viene generata un'eccezione e il messaggio all'interno dell'eccezione è:

Errore di comunicazione: la connessione socket è stata interrotta. Questo potrebbe essere causato da da un errore di elaborazione del tuo messaggio o un timeout di ricezione superata dall'host remoto, o un problema di risorse di rete sottostante. Locale timeout presa era '00: 00: 59,9,687494' millions

(Questo non è un timeout si verifica l'errore immediatamente.)

Come più volte evidenziato, posso risolvere questo problema a livello di codice come segue:

var binding = new NetTcpBinding 
{ 
    ReaderQuotas = { MaxArrayLength = 10000000 } 
}; 

return new ChannelFactory<IRemoteDataRequester>(binding); 

funziona bene, ma ho bisogno di farlo via config per scopi di test.

Ho anche provato la seguente:

var binding = new NetTcpBinding("unsecureNetTcpBinding"); 
return new ChannelFactory<IRemoteDataRequester>(binding); 

Ma questo non fa differenza.

Quindi la mia domanda è perché, quando creo il canale dalla configurazione endpoint che include un'associazione con MaxArrayLength impostato su un valore adatto, questo valore viene ignorato?

Molti saluti.

Ok, ho trovato la soluzione. La configurazione funzionava da sempre.Tuttavia, la configurazione che ho fornito ("unsecureNetTcpBinding") che ho trovato da un esempio di codice che illustra i servizi http (non il servizio di rete tcp che è quello che sto progettando). La parte errata della configurazione era 'security mode = "None"' Quando l'ho risolto, ha funzionato. Se cambio readerQuotas maxArrayLength questo viene applicato come richiesto. Il motivo per cui il mio codice ha funzionato è perché non stavo impostando la modalità di sicurezza su none. Grazie per i tuoi commenti e assistenza.

risposta

1

Penso che il problema potrebbe essere che in configurazione il tuo numero ha solo 6 zeri, mentre nel codice hai 7 zeri. Può essere?

0

Forse MaxArrayLength non è la proprietà giusta da impostare.

Prova "MaxBufferSize" e "MaxBufferPoolSize":

<bindings> 
     <netTcpBinding> 
      <binding name="unsecureNetTcpBinding" 
        maxBufferSize="2147483647" 
        maxBufferPoolSize="2147483647" 
        maxReceivedMessageSize="2147483647"> 
       <readerQuotas maxArrayLength="1000000" /> 
       <security mode="None" /> 
      </binding> 
     </netTcpBinding> 
    </bindings> 

Ma la vera domanda è: se si dispone di grandi quantità di dati, perché non stai facendo uso di WCF streaming ?? Questo è esattamente ciò per cui è stato progettato.

http://www.haveyougotwoods.com/archive/2008/04/14/wcf-message-streaming.aspx

Il MaxBufferSize ecc formati sono impostati su un valore abbastanza piccolo di proposito - per evitare attacchi denial of service. Semplicemente aumentando i livelli MaxInt, il server diventa vulnerabile a questi attacchi DOS.

UPDATE:
provare a fare questo: - creare una nuova console app - aggiungere riferimenti a System.Runtime.Serialization e System.ServiceModel - aggiungere un app.config che contiene esattamente ciò che il vostro lato client config contiene - mettere queste righe del codice nel tuo console app:

class Program 
    { 
     static void Main(string[] args) 
     { 
      NetTcpBinding binding = new NetTcpBinding("unsecureNetTcpBinding"); 
      int maxArrayLength = binding.ReaderQuotas.MaxArrayLength; 
      long maxReceivedMessageSize = binding.MaxReceivedMessageSize; 
     } 
    } 
  • corsa e il debug - quali valori si ottiene ?? Ricevo esattamente ciò che hai inserito: "1000000" per binding.ReaderQuotas.MaxArrayLength, "2147483647" per binding.MaxReceivedMessageSize.

WCF riconosce e utilizza tali impostazioni dalla configurazione - 120% garantito. Deve esserci qualcos'altro in corso nella tua app .....

+0

Ho provato a impostare maxBufferSize, maxBufferPoolSize e maxReceivedMessageSize ma questi non funzionano tramite la configurazione. Solo per ribadire, posso risolvere questo problema via codice con maxArrayLength, ma voglio sapere come farlo via config, evviva – Zephilim

+0

Sto impostando maxBufferSize e MaxArrayLength in configurazione - nessun problema. Ci deve essere qualcos'altro che accade nel tuo caso ..... –

Problemi correlati