(WCF) Problem mit Nachrichtengröße



  • Hi Leutz,

    ich habe eine einfache Client-Server-Anwendung mit WCF geschreiben, bei der der Client auf dem Server eine Methode aufruft und der Server über eine Callback-Methode ein String-Array an den Client zurückliefert. Das funktioniert prinzipiell auch, nur sobald das vom Server an den Client übermittelte String-Array mehr als 65535 Elemente hat, wird es nicht mehr übertragen. Es wird auch keine Exception ausgegeben, es kommt schlicht und ergreifend nichts mehr beim Client an. Nun ist ja der Default-Wert der "MaxReceivedMessageSize"-Eigenschaft 65536 Byte und die Vermutung liegt ja nahe, dass es damit etwas zu tun haben könnte. Allerdings hat eine Erhöhung des Wertes nichts gebracht. Im folgenden einmal der Code zur Initialisierung der Verbindung auf Server- und Client-Seite. Vielleicht hat ja jemand von Euch einen Tip für mich 🙂

    Code auf Serverseite:

    rateServer = new CServer();
    
                    ServiceHost serverHost =
                        new ServiceHost(rateServer);
    
                    NetTcpBinding binding =
                        new NetTcpBinding(SecurityMode.None, true);
                    Uri address =
                        new Uri(@endpoint_adress);
    
                    int value = 2147483647;
    
                    XmlDictionaryReaderQuotas rq = new XmlDictionaryReaderQuotas();
                    rq.MaxArrayLength = value;
                    rq.MaxStringContentLength = value;
                    rq.MaxBytesPerRead = value;
    
                    binding.ReaderQuotas = rq;
                    binding.MaxBufferPoolSize = value;
                    binding.MaxBufferSize = value;
                    binding.MaxReceivedMessageSize = value;
    
                    serverHost.AddServiceEndpoint(
                        typeof(IRateService), binding, address);
    
                    serverHost.Open();
    

    Code auf Clientseite:

    System.ServiceModel.Channels.Binding binding =
                    new NetTcpBinding(SecurityMode.None, true);
                    EndpointAddress address =
                        new EndpointAddress(@endpoint_adress);
    
                    int value = 2147483647;
    
                    XmlDictionaryReaderQuotas rq = new XmlDictionaryReaderQuotas();
                    rq.MaxArrayLength = value;
                    rq.MaxStringContentLength = value;
                    rq.MaxBytesPerRead = value;
    
                    ((NetTcpBinding)binding).ReaderQuotas = rq;
                    ((NetTcpBinding)binding).MaxReceivedMessageSize = value;
                    ((NetTcpBinding)binding).MaxBufferSize = value;
                    ((NetTcpBinding)binding).MaxBufferPoolSize = value;
    
                    InstanceContext context = new InstanceContext(this);
    
                    DuplexChannelFactory<IRateService> factory =
                        new DuplexChannelFactory<IRateService>
                        (context, binding, address);
    
                    proxy = factory.CreateChannel();
    

    Ergänzend noch das Gerüst der CServer-Klasse, welche den eigentlichen Server-Vertrag implementiert:

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
    ConcurrencyMode = ConcurrencyMode.Reentrant, MaxItemsInObjectGraph=1000000)]
    public class CServer : IRateService
    {
       ...
    }
    

    Wäre super wenn Ihr mir helfen könntet. Bin mit meinem Latein langesam echt am Ende.

    Gruß,
    Chris



  • 1. Exceptions werden mit Sicherheit generiert nur möglicherweise nicht an den Client aus Sicherheitsgründen gesendet. Im "Entwicklungsmodus" kann dieses geändert werden (web.config des Services):

    <behaviors>
                <serviceBehaviors>
                    <behavior name="...">
                        <serviceDebug includeExceptionDetailInFaults="true" />
                    </behavior>
    

    Für den "Produktionsmodus" empfiehlt es sich die Exceptions in ein Log zu schreiben, beispielsweise in das Eventlog der Maschine.
    2. Wenn du die Elemente im Objektgraphen erhöhen willst, änderst du das ebenfalls an der Stelle (web.config des Services):

    <behaviors>
                <serviceBehaviors>
                    <behavior name="...">
                        <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
                    </behavior>
    

    Gern vergessen wird dass das im Client und im Service geändert werden muss (app.config des Clients):

    <system.serviceModel>
            <behaviors>
                <endpointBehaviors>
                    <behavior name="oasmServiceBehavior">
                        <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
                    </behavior>
                </endpointBehaviors>
            </behaviors>
    

    3. Wenn die Objekte/Message zu groß/lang sind, kannst du das im Client in den Bindings ändern:

    <bindings>
                <wsHttpBinding>
                    <binding name="..." maxReceivedMessageSize="2147483647" />
                 </binding>
    

    BTW, es ist einfacher die Konfiguration in XML vorzunehmen. Im VS gibt es dazu ein WCF-Konfigurationstool was für Client und Service geeignet ist.



  • 100.000 DANK AN DICH WITTE!!!!!

    Jetzt gehts es. Habe in der Tat vergessen, die maxItemsInObjectGraph-Eigenschaft auch beim Client zu definieren.

    Im übrigen hab ich die Konfiguriation jetzt auch in die App.config augelagert, was sich wirklich besser macht.

    Danke nochmal, Du hast meinen Tag gerettet 🙂

    Greetz,
    Chris


Anmelden zum Antworten