WCF - Comment augmenter le quota de taille de message


454

J'ai un service WCF qui renvoie 1000 enregistrements de la base de données au client. J'ai un client ASP.NET WCF (j'ai ajouté une référence de service dans le projet d'application Web asp.net pour consommer WCF).

J'obtiens le message suivant lorsque j'exécute l'application cliente:

Le quota de taille de message maximum pour les messages entrants (65536) a été dépassé. Pour augmenter le quota, utilisez la propriété MaxReceivedMessageSize sur l'élément de liaison approprié.

De l'aide? Comment augmenter le quota de taille des messages?


J'ai eu le même problème, mais je viens de recevoir une erreur de réseau inamicale 400, mais la solution était le truc de la taille du message ..
Mr W

2
J'ai résolu le problème en utilisant les étapes mentionnées dans [le lien] [1] [1]: stackoverflow.com/questions/7476853/...
Ram

Pourquoi est-il si bas par défaut? Sécurité?
Coops

@Coops pour la sécurité en effet. En définissant un quota sur les messages, par exemple, les attaques DDOS sont (au moins un peu) plus difficiles à exécuter.
Peter van Kekem

Réponses:


608

Vous voudrez quelque chose comme ça pour augmenter les quotas de taille de message, dans le fichier App.config ou Web.config :

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

Et utilisez le nom de liaison dans votre configuration de point de terminaison, par exemple

...
bindingConfiguration="basicHttp"
...

La justification des valeurs est simple, elles sont suffisamment grandes pour accueillir la plupart des messages. Vous pouvez régler ce nombre en fonction de vos besoins. La faible valeur par défaut est essentiellement là pour empêcher les attaques de type DOS. Le faire 20000000 permettrait à une attaque DOS distribuée d'être efficace, la taille par défaut de 64k nécessiterait un très grand nombre de clients pour maîtriser la plupart des serveurs de nos jours.


20
Merci ... Cette modification doit être effectuée dans le fichier web.config de l'application cliente.
bugBurger

8
Vous devrez peut-être également le modifier sur le serveur - dans le cas où vous devez envoyer un grand ensemble de données en tant que paramètre à une méthode WCF.
Nate

9
Il est suffisamment grand pour accueillir la plupart des messages. Vous pouvez régler ce nombre en fonction de vos besoins. Il est essentiellement là pour empêcher les attaques de type DOS. Le faire 20000000 permettrait à une attaque DOS distribuée d'être efficace, la taille par défaut de 64k nécessiterait un très grand nombre de clients pour maîtriser la plupart des serveurs de nos jours.
Nate

18
Pour ceux qui sont intéressés, j'ai lu sur un autre blog que la taille maximale est 2147483647. 20000000 est un peu plus petit que ce nombre, donc utiliser le plus petit nombre avec lequel vous pouvez vous en sortir sans interrompre le service est logique.
proudgeekdad

5
@Slauma Il devrait être modifié sur le serveur si ce paramètre entrant était trop volumineux; sinon (et plus probablement), la modification doit être effectuée dans le fichier de configuration client, car c'est la réponse du service (et non son paramètre) qui est trop importante.
Nate

155

Si vous obtenez toujours ce message d'erreur lors de l'utilisation du client de test WCF, c'est parce que le client a un paramètre MaxBufferSize distinct .

Pour corriger le problème:

  1. Cliquez avec le bouton droit sur le nœud du fichier de configuration au bas de l'arborescence
  2. Sélectionnez Modifier avec SvcConfigEditor

Une liste de paramètres modifiables apparaîtra, y compris MaxBufferSize.

Remarque: les clients proxy générés automatiquement définissent également MaxBufferSize sur 65536 par défaut.


8
Pourquoi oh pourquoi j'oublie toujours ça? +1
James Skemp

9
Sur vs2013 SvcConfigEditor est remplacé par Modifier la configuration WCF si les gens le recherchent.
ZoomVirus

Vous ne trouvez pas SVCconfigEditor?
Arul Sidthan

Vous le trouverez dans le dossier Bindings, cliquez sur la liaison pour le service et c'est là.
Sameer Alibhai du

Si votre fichier de configuration est généré automatiquement, vous devez absolument le faire de cette façon. Chaque fois que vous mettez à jour votre référence, il régénérera app.config et vous devrez le modifier manuellement à nouveau. Si vous le modifiez VS cependant, les nouvelles modifications s'adapteront aux paramètres que vous avez choisis.
kingfrito_5005

104

Si vous créez dynamiquement vos liaisons WCF, voici le code à utiliser:

BasicHttpBinding httpBinding = new BasicHttpBinding();
httpBinding.MaxReceivedMessageSize = Int32.MaxValue;
httpBinding.MaxBufferSize = Int32.MaxValue;
// Commented next statement since it is not required
// httpBinding.MaxBufferPoolSize = Int32.MaxValue;

Vous pouvez l'utiliser initialiser. De toute évidence, vous pouvez l'utiliser comme méthode constructeur.
aemre

45

Le client de test WCF a sa propre configuration client.

Exécutez le client de test et faites défiler vers le bas. Si vous double-cliquez sur le nœud Fichier de configuration, vous verrez la représentation XML. Comme vous pouvez le voir maxReceivedMessageSizeest 65536.

Pour modifier cela, cliquez avec le bouton droit sur le nœud de l'arborescence du fichier de configuration et sélectionnez Modifier avec SvcConfigEditor. Lorsque l'éditeur s'ouvre, développez Liaisons et double-cliquez sur la liaison qui a été générée automatiquement.

Vous pouvez modifier toutes les propriétés ici, y compris maxReceivedMessageSize. Lorsque vous avez terminé, cliquez sur Fichier - Enregistrer .

Enfin, lorsque vous êtes de retour dans la fenêtre Client de test WCF, cliquez sur Outils - Options .

REMARQUE : décochez la configuration Toujours régénérer lors du lancement des services .


2
Probablement la meilleure réponse ici!
Haris

3
voter en raison de la note pour décocher l' Always regenerate configoption.
furier

Résolution la plus simple à mon avis. M'a sauvé des maux de tête.
Jared Beach

Sur vs2013 SvcConfigEditor est remplacé par Modifier la configuration WCF si les gens le recherchent.
ZoomVirus

Je vous remercie. Je me suis cassé la tête pendant un certain temps, en changeant la configuration du serveur encore et encore, lorsque le problème était avec la configuration du client de test!
Fahad

24

J'ai trouvé le moyen facile

--- cliquez avec le bouton droit sur le fichier de configuration webconfig ou app et cliquez sur MODIFIER LA CONFIGURATION WCF et accédez à bingdigs et sélectionnez le service de votre choix et le côté droit affiche maxReciveMessageSize donne un grand nombre ---


2
Ce fut une excellente réponse, je ne savais pas que je pouvais éditer à partir d'ici, Merci
albert sh

8

Je résous le problème ... comme suit

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

20
En quoi cela diffère-t-il de ma solution? Autre que vous avez inclus toutes les parties non pertinentes de votre configuration ainsi que les parties pertinentes et vous avez choisi la valeur maximale possible au lieu des 200m que j'ai choisis?
Nate

3
Le contexte est bon aussi ... peut-être que ces deux réponses pourraient être fusionnées?
Jeff

1
ce paramètre est-il configuré sur le serveur ou le client?
John Kenedy

8

J'ai résolu mon problème sur Bing Maps WPF sur mon projet Utilisation de CalculateRoute (). Dans mon cas, la solution consistait à définir maxReceivedMessageSize et maxReceivedMessageSize sur l'attribut "httpTransport" pour la section "customBinding".

J'ai défini dans le fichier applications.config (es. MyApp.config) cette configuration:

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

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>


Idéal pour publier votre réponse. Il est important que la valeur "bindingConfiguration" corresponde au nom de la liaison. Dans votre exemple "wsHttpBinding_Username".
Bruno Bieri

6

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

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

IMPORTANT:

Si vous essayez de passer un objet complexe qui a de nombreux objets connectés (par exemple: une structure de données arborescente, une liste qui a de nombreux objets ...), la communication échouera, quelle que soit la façon dont vous avez augmenté les quotas. Dans de tels cas, vous devez augmenter le nombre d'objets contenant:

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

La maxItemsInObjectGraphest la solution (rapide) pour moi. Mais lorsque vous augmentez cela, vous devez vous demander si la meilleure solution consiste pour votre application à demander des données par blocs, par opposition à un énorme graphique d'objet qui peut épuiser les ressources.
Paul

6

Pour moi, tout ce que j'avais à faire était d'ajouter maxReceivedMessageSize="2147483647"au client app.config. Le serveur est resté intact.


5

Une autre chose importante à considérer de mon expérience ..

Je conseillerais fortement de NE PAS maximiser maxBufferPoolSize, car les tampons du pool ne sont jamais libérés tant que le domaine d'application (c'est-à-dire le pool d'applications) ne recycle pas.

Une période de trafic élevé peut entraîner l'utilisation et la libération de beaucoup de mémoire.

Plus de détails ici:


3

N'oubliez pas que le fichier app.config du point d'entrée d'exécution sera pris en compte, pas le projet de bibliothèque de classe gérant les appels de service Web s'il y en a un.

Par exemple, si vous obtenez l'erreur lors de l'exécution du test unitaire, vous devez configurer la configuration appropriée dans le projet de test.


0

j'ai cette erreur lors de l'utilisation de ces paramètres sur web.config

System.ServiceModel.ServiceActivationException

j'ai défini des paramètres comme celui-ci:

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


4
Donc, vous avez résolu votre problème en utilisant la réponse de Nate, puis vous l'avez publié comme le vôtre. Pas cool.
arcain

La réponse de @arcain Nates était très générique, utilisant des noms et des numéros de stock qui devraient apparaître fréquemment. Cette réponse n'a pas été volée, c'est tout simplement la bonne réponse. Comme il n'y a qu'une seule bonne réponse, elle devait être répétée.
kingfrito_5005

@ kingfrito_5005 La "bonne" réponse était déjà là lorsque le répondeur a posté cela. Il a assez clairement soulevé l' bindingsélément de Nate et l'a republié dans le cadre de sa réponse. Ces 2000000valeurs sont assez distinctes.
arcain

@arcain, je ne suis pas d'accord, ce sont des valeurs très standard, mon entreprise les utilise également dans nos éléments de liaison.
kingfrito_5005
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.