WCF - So erhöhen Sie das Kontingent für die Nachrichtengröße

454

Ich habe einen WCF-Dienst, der 1000 Datensätze aus der Datenbank an den Client zurückgibt. Ich habe einen ASP.NET WCF-Client (ich habe im asp.net-Webanwendungsprojekt eine Dienstreferenz hinzugefügt, um WCF zu verwenden).

Beim Ausführen der Clientanwendung wird folgende Meldung angezeigt:

Das maximale Kontingent für die Nachrichtengröße für eingehende Nachrichten (65536) wurde überschritten. Verwenden Sie zum Erhöhen des Kontingents die MaxReceivedMessageSize-Eigenschaft für das entsprechende Bindungselement.

Irgendeine Hilfe? Wie kann das Kontingent für die Nachrichtengröße erhöht werden?

bugBurger
quelle
Ich hatte das gleiche Problem, aber ich habe gerade einen unfreundlichen Netzwerkfehler 400 erhalten, aber die Lösung war das Nachrichtengrößen-Ding.
Mr W
2
Ich habe das Problem mithilfe der in [dem Link] [1] [1] genannten Schritte gelöst: stackoverflow.com/questions/7476853/…
Ram
Warum ist es standardmäßig so niedrig eingestellt? Sicherheit?
Coops
@Coops für die Sicherheit in der Tat. Durch das Festlegen eines Kontingents für die Nachrichten sind beispielsweise DDOS-Angriffe (zumindest ein wenig) schwieriger auszuführen.
Peter van Kekem

Antworten:

608

Sie möchten, dass so etwas die Kontingente für die Nachrichtengröße in der Datei App.config oder Web.config erhöht :

<bindings>
    <basicHttpBinding>
        <binding name="basicHttp" allowCookies="true"
                 maxReceivedMessageSize="20000000" 
                 maxBufferSize="20000000"
                 maxBufferPoolSize="20000000">
            <readerQuotas maxDepth="32" 
                 maxArrayLength="200000000"
                 maxStringContentLength="200000000"/>
        </binding>
    </basicHttpBinding>
</bindings>

Verwenden Sie den Bindungsnamen in Ihrer Endpunktkonfiguration, z

...
bindingConfiguration="basicHttp"
...

Die Begründung für die Werte ist einfach, sie sind ausreichend groß, um die meisten Nachrichten aufzunehmen. Sie können diese Nummer an Ihre Bedürfnisse anpassen. Der niedrige Standardwert dient grundsätzlich dazu, Angriffe vom Typ DOS zu verhindern. Wenn 20000000 aktiviert wird, kann ein verteilter DOS-Angriff effektiv ausgeführt werden. Die Standardgröße von 64 KB würde heutzutage eine sehr große Anzahl von Clients erfordern, um die meisten Server zu überlasten.

Nate
quelle
20
Danke. Diese Änderung muss in der Datei web.config der Clientanwendung vorgenommen werden.
BugBurger
8
Möglicherweise müssen Sie es auch auf dem Server ändern - für den Fall, dass Sie ein großes Dataset als Parameter an eine WCF-Methode senden müssen.
Nate
9
Es ist ausreichend groß, um die meisten Nachrichten aufzunehmen. Sie können diese Nummer an Ihre Bedürfnisse anpassen. Es ist im Grunde genommen dazu da, Angriffe vom Typ DOS zu verhindern. Wenn 20000000 aktiviert wird, kann ein verteilter DOS-Angriff effektiv ausgeführt werden. Die Standardgröße von 64 KB würde eine sehr große Anzahl von Clients erfordern, um die meisten Server heutzutage zu überlasten.
Nate
18
Für andere Interessierte habe ich in einem anderen Blog gelesen, dass die maximale Größe 2147483647 beträgt. 20000000 ist etwas kleiner als diese Zahl. Daher ist es sinnvoll, die kleinste Zahl zu verwenden, mit der Sie durchkommen können, ohne den Dienst zu unterbrechen.
Pridegeekdad
5
@Slauma Es müsste auf dem Server geändert werden, wenn dieser eingehende Parameter zu groß wäre. Andernfalls (und wahrscheinlicher) muss die Änderung in der Client-Konfigurationsdatei vorgenommen werden, da die Antwort des Dienstes (nicht sein Parameter) zu groß ist.
Nate
155

Wenn diese Fehlermeldung bei Verwendung des WCF- Testclients weiterhin angezeigt wird , liegt dies daran, dass der Client über eine separate MaxBufferSize- Einstellung verfügt.

So beheben Sie das Problem:

  1. Klicken Sie mit der rechten Maustaste auf den Knoten Konfigurationsdatei am unteren Rand des Baums
  2. Wählen Sie Mit SvcConfigEditor bearbeiten

Eine Liste der bearbeitbaren Einstellungen wird angezeigt, einschließlich MaxBufferSize.

Hinweis: Automatisch generierte Proxy-Clients setzen MaxBufferSize standardmäßig auf 65536.

Michael Rodrigues
quelle
8
Warum oh warum vergesse ich das immer? +1
James Skemp
9
Auf vs2013 wird SvcConfigEditor durch Edit WCF configuration ersetzt, wenn Leute danach suchen.
ZoomVirus
SVCconfigEditor nicht gefunden?
Arul Sidthan
Sie finden es im Ordner "Bindungen". Klicken Sie auf die Bindung für den Service und sie befindet sich dort.
Sameer Alibhai
Wenn Ihre Konfigurationsdatei automatisch generiert wird, sollten Sie dies unbedingt auf diese Weise tun. Jedes Mal, wenn Sie Ihre Referenz aktualisieren, wird die app.config neu generiert und Sie müssen sie erneut manuell ändern. Wenn Sie es VS ändern, werden die neuen Änderungen den von Ihnen gewählten Einstellungen angepasst.
kingfrito_5005
104

Wenn Sie Ihre WCF-Bindungen dynamisch erstellen, ist folgender Code zu verwenden:

BasicHttpBinding httpBinding = new BasicHttpBinding();
httpBinding.MaxReceivedMessageSize = Int32.MaxValue;
httpBinding.MaxBufferSize = Int32.MaxValue;
// Commented next statement since it is not required
// httpBinding.MaxBufferPoolSize = Int32.MaxValue;
Bharath K.
quelle
Sie können es initialisieren verwenden. Natürlich können Sie damit Ihre Konstruktormethode verwenden.
Aemre
45

Der WCF-Testclient verfügt über eine eigene Clientkonfiguration.

Führen Sie den Testclient aus und scrollen Sie nach unten. Wenn Sie auf den Knoten Konfigurationsdatei doppelklicken, wird die XML-Darstellung angezeigt. Wie Sie sehen können, maxReceivedMessageSizeist das 65536.

Um dies zu bearbeiten, klicken Sie mit der rechten Maustaste auf den Baumknoten Konfigurationsdatei und wählen Sie Bearbeiten mit SvcConfigEditor. Wenn der Editor geöffnet wird, erweitern Sie Bindungen und doppelklicken Sie auf die automatisch generierte Bindung.

Sie können hier alle Eigenschaften bearbeiten, einschließlich maxReceivedMessageSize. Wenn Sie fertig sind, klicken Sie auf Datei - Speichern .

Wenn Sie wieder im Fenster des WCF-Testclients sind, klicken Sie auf Extras - Optionen .

Hinweis : Deaktivieren Sie das Kontroll immer Regenerat Config , wenn Dienste starten .

Jodee Dex Seite
quelle
2
Wahrscheinlich die beste Antwort hier!
Haris
3
Upvote wegen des Hinweises zum Deaktivieren der Always regenerate configOption.
wütender
Einfachste Lösung meiner Meinung nach. Hat mir Kopfschmerzen erspart.
Jared Beach
Auf vs2013 wird SvcConfigEditor durch Edit WCF configuration ersetzt, wenn Leute danach suchen.
ZoomVirus
Vielen Dank. Ich habe mir eine Weile den Kopf gebrochen und die Serverkonfiguration immer wieder geändert, als das Problem bei der Testclient-Konfiguration lag!
Fahad
24

Ich habe den einfachen Weg gefunden

--- Klicken Sie mit der rechten Maustaste auf die Webkonfigurations- oder App-Konfigurationsdatei und klicken Sie auf WCF-KONFIGURATION BEARBEITEN. Gehen Sie zu Bingdigs und wählen Sie Ihren Dienst aus. Zeigen Sie rechts maxReciveMessageSize an. Geben Sie eine große Zahl an

NC64
quelle
2
Es war eine großartige Antwort, ich wusste nicht, dass ich von hier aus bearbeiten kann. Danke
albert sh
8

Ich löse das Problem ... wie folgt

    <bindings>
  <netTcpBinding>
    <binding name="ECMSBindingConfig" closeTimeout="00:10:00" openTimeout="00:10:00"
      sendTimeout="00:10:00" maxBufferPoolSize="2147483647" maxBufferSize="2147483647"
      maxReceivedMessageSize="2147483647" portSharingEnabled="true">
      <readerQuotas maxArrayLength="2147483647" maxNameTableCharCount="2147483647"
          maxStringContentLength="2147483647" maxDepth="2147483647"
          maxBytesPerRead="2147483647" />
      <security mode="None" />
    </binding>
  </netTcpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior name="ECMSServiceBehavior">
      <dataContractSerializer ignoreExtensionDataObject="true" maxItemsInObjectGraph="2147483647" />
      <serviceDebug includeExceptionDetailInFaults="true" />
      <serviceTimeouts transactionTimeout="00:10:00" />
      <serviceThrottling maxConcurrentCalls="200" maxConcurrentSessions="100"
        maxConcurrentInstances="100" />
    </behavior>
  </serviceBehaviors>
</behaviors>
Rajesh Kuamr Chekuri
quelle
20
Wie unterscheidet sich das von meiner Lösung? Abgesehen davon, dass Sie alle irrelevanten Teile Ihrer Konfiguration sowie die relevanten Teile einbezogen haben und statt der von mir gewählten 200 m den maximal möglichen Wert gewählt haben?
Nate
3
Der Kontext ist auch gut ... vielleicht könnten diese beiden Antworten zusammengeführt werden?
Jeff
1
Ist diese Einstellung auf dem Server oder Client zu konfigurieren?
John Kenedy
8

Ich habe mein Problem mit Bing Maps WPF in meinem Projekt mit CalculateRoute () gelöst. In meinem Fall bestand die Lösung darin, die Werte maxReceivedMessageSize und maxReceivedMessageSize für das Attribut "httpTransport" für den Abschnitt "customBinding" festzulegen.

Ich habe in der Datei applications.config (es. MyApp.config) folgende Konfiguration festgelegt:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IGeocodeService" />
            <binding name="BasicHttpBinding_IRouteService" />
        </basicHttpBinding>
        <customBinding>
            <binding name="CustomBinding_IGeocodeService">
                <binaryMessageEncoding />
              <httpTransport manualAddressing="false" maxBufferPoolSize="524288"
                                maxReceivedMessageSize="2147483647" allowCookies="false" authenticationScheme="Anonymous"
                                bypassProxyOnLocal="false" decompressionEnabled="true" hostNameComparisonMode="StrongWildcard"
                                keepAliveEnabled="true" maxBufferSize="2147483647" proxyAuthenticationScheme="Anonymous"
                                realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
                                useDefaultWebProxy="true" />
            </binding>
            <binding name="CustomBinding_IRouteService">
                <binaryMessageEncoding />
              <httpTransport manualAddressing="false" maxBufferPoolSize="524288"
                                maxReceivedMessageSize="2147483647" allowCookies="false" authenticationScheme="Anonymous"
                                bypassProxyOnLocal="false" decompressionEnabled="true" hostNameComparisonMode="StrongWildcard"
                                keepAliveEnabled="true" maxBufferSize="2147483647" proxyAuthenticationScheme="Anonymous"
                                realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
                                useDefaultWebProxy="true" />
            </binding>
        </customBinding>
    </bindings>
    <client>
        <endpoint address="http://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IGeocodeService"
            contract="BingServices.IGeocodeService" name="BasicHttpBinding_IGeocodeService" />
        <endpoint address="http://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc/binaryHttp"
            binding="customBinding" bindingConfiguration="CustomBinding_IGeocodeService"
            contract="BingServices.IGeocodeService" name="CustomBinding_IGeocodeService" />
        <endpoint address="http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IRouteService"
            contract="BingServices.IRouteService" name="BasicHttpBinding_IRouteService" />
        <endpoint address="http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc/binaryHttp"
            binding="customBinding" bindingConfiguration="CustomBinding_IRouteService"
            contract="BingServices.IRouteService" name="CustomBinding_IRouteService" />
    </client>
</system.serviceModel>
Francesco Germinara
quelle
6

<bindings>
  <wsHttpBinding>
    <binding name="wsHttpBinding_Username" maxReceivedMessageSize="20000000"          maxBufferPoolSize="20000000">
      <security mode="TransportWithMessageCredential">
        <message clientCredentialType="UserName" establishSecurityContext="false"/>
      </security>
    </binding>
  </wsHttpBinding>
</bindings>

<client>
  <endpoint
            binding="wsHttpBinding"
            bindingConfiguration="wsHttpBinding_Username"
            contract="Exchange.Exweb.ExchangeServices.ExchangeServicesGenericProxy.ExchangeServicesType"
            name="ServicesFacadeEndpoint" />
</client>

Hemant Soni
quelle
Hervorragend geeignet, um Ihre Antwort zu veröffentlichen. Es ist wichtig, dass der Wert "bindingConfiguration" mit dem Bindungsnamen übereinstimmt. In Ihrem Beispiel "wsHttpBinding_Username".
Bruno Bieri
6

Für HTTP:

<bindings>
  <basicHttpBinding>
    <binding name="basicHttp" allowCookies="true"
             maxReceivedMessageSize="20000000" 
             maxBufferSize="20000000"
             maxBufferPoolSize="20000000">
        <readerQuotas maxDepth="200" 
             maxArrayLength="200000000"
             maxBytesPerRead="4096"
             maxStringContentLength="200000000"
             maxNameTableCharCount="16384"/>
    </binding>
  </basicHttpBinding>
</bindings>

Für TCP:

<bindings>
  <netTcpBinding>
    <binding name="tcpBinding"
             maxReceivedMessageSize="20000000"
             maxBufferSize="20000000"
             maxBufferPoolSize="20000000">
      <readerQuotas maxDepth="200"
           maxArrayLength="200000000"
           maxStringContentLength="200000000"
           maxBytesPerRead="4096"
           maxNameTableCharCount="16384"/>
    </binding>
  </netTcpBinding>
</bindings>

WICHTIG:

Wenn Sie versuchen, ein komplexes Objekt mit vielen verbundenen Objekten zu übergeben (z. B. eine Baumdatenstruktur, eine Liste mit vielen Objekten ...), schlägt die Kommunikation fehl, unabhängig davon, wie Sie die Kontingente erhöht haben. In solchen Fällen müssen Sie die Anzahl der enthaltenen Objekte erhöhen:

<behaviors>
  <serviceBehaviors>
    <behavior name="NewBehavior">
      ...
      <dataContractSerializer maxItemsInObjectGraph="2147483646"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
Jacob
quelle
Das maxItemsInObjectGraphwar die (schnelle) Lösung für mich. Wenn Sie dies jedoch erhöhen, sollten Sie darüber nachdenken, ob die bessere Lösung für Ihre Anwendung darin besteht, Daten in Blöcken anzufordern, im Gegensatz zu einem riesigen Objektdiagramm, das Ressourcen belasten kann.
Paul
6

Für mich war alles, was ich tun musste maxReceivedMessageSize="2147483647", dem Client app.config hinzuzufügen. Der Server blieb unberührt.

Ashilon
quelle
5

Eine weitere wichtige Sache aus meiner Erfahrung zu berücksichtigen ..

Ich würde dringend empfehlen, maxBufferPoolSize NICHT zu maximieren, da Puffer aus dem Pool erst freigegeben werden, wenn die App-Domäne (dh der Anwendungspool) recycelt wird.

Eine Zeit mit hohem Datenverkehr kann dazu führen, dass viel Speicher verwendet und nie freigegeben wird.

Weitere Details hier:

Valerio Gentile
quelle
3

Vergessen Sie nicht, dass die app.config des Ausführungseintrittspunkts berücksichtigt wird, nicht die im Klassenbibliotheksprojekt, die Web-Service-Aufrufe verwaltet, falls vorhanden.

Wenn Sie beispielsweise beim Ausführen des Komponententests den Fehler erhalten, müssen Sie im Testprojekt die entsprechende Konfiguration einrichten.

Gab
quelle
0

Ich habe diesen Fehler erhalten, wenn ich diese Einstellungen auf web.config verwendet habe

System.ServiceModel.ServiceActivationException

Ich stelle Einstellungen wie folgt ein:

      <service name="idst.Controllers.wcf.Service_Talks">
    <endpoint address="" behaviorConfiguration="idst.Controllers.wcf.Service_TalksAspNetAjaxBehavior"
      binding="webHttpBinding" contract="idst.Controllers.wcf.Service_Talks" />
  </service>
  <service name="idst.Controllers.wcf.Service_Project">
    <endpoint address="" behaviorConfiguration="idst.Controllers.wcf.Service_ProjectAspNetAjaxBehavior"
      binding="basicHttpBinding" bindingConfiguration="" bindingName="largBasicHttp"
      contract="idst.Controllers.wcf.Service_Project" />
  </service>
</services>

<bindings>
<basicHttpBinding>
    <binding name="largBasicHttp" allowCookies="true"
             maxReceivedMessageSize="20000000"
             maxBufferSize="20000000"
             maxBufferPoolSize="20000000">
        <readerQuotas maxDepth="32"
             maxArrayLength="200000000"
             maxStringContentLength="200000000"/>
    </binding>
</basicHttpBinding>

FARHAD AFSAR
quelle
4
Sie haben Ihr Problem also mithilfe der Antwort von Nate behoben und dann als Ihre eigene veröffentlicht. Uncool.
Arcain
Die Antwort von @arcain Nates war sehr allgemein gehalten und verwendete Aktiennamen und -nummern, von denen zu erwarten ist, dass sie häufig auftauchen. Diese Antwort wurde nicht gestohlen, es ist einfach die richtige Antwort. Da es nur eine richtige Antwort gibt, musste sie wiederholt werden.
kingfrito_5005
@ kingfrito_5005 Die "richtige" Antwort war bereits hier, als der Antwortende dies gepostet hat. Er hob Nates bindingsElement ziemlich deutlich auf und veröffentlichte es als Teil seiner Antwort erneut. Diese 2000000Werte sind ziemlich unterschiedlich.
Arcain
@arcain, ich bin nicht der Meinung, dass dies sehr Standardwerte sind. Mein Unternehmen verwendet sie auch in unseren verbindlichen Elementen.
kingfrito_5005