web-dev-qa-db-fra.com

Demande de service Web WCF volumineuse échouant avec (400) requête HTTP incorrecte

J'ai rencontré ce problème apparemment commun et je suis incapable de le résoudre.

Si j'appelle mon service Web WCF avec un nombre relativement petit d'éléments dans un paramètre de tableau (j'ai testé jusqu'à 50), tout va bien.

Cependant, si j'appelle le service Web avec 500 éléments, j'obtiens l'erreur Bad Request.

Fait intéressant, j'ai exécuté Wireshark sur le serveur et il semble que la demande ne frappe même pas le serveur - l'erreur 400 est générée du côté client.

L'exception est la suivante:

System.ServiceModel.ProtocolException: The remote server returned an unexpected response: (400) Bad Request. ---> System.Net.WebException: The remote server returned an error: (400) Bad Request.

La section system.serviceModel De mon fichier de configuration client est:

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="WSHttpBinding_IMyService" closeTimeout="00:01:00"
                openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"
                messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                allowCookies="false">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="2147483647"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00"
                    enabled="false" />
                <security mode="None">
                    <transport clientCredentialType="Windows" proxyCredentialType="None"
                        realm="" />
                    <message clientCredentialType="Windows" negotiateServiceCredential="true"
                        establishSecurityContext="true" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://serviceserver/MyService.svc"
            binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMyService"
            contract="SmsSendingService.IMyService" name="WSHttpBinding_IMyService" />
    </client>
</system.serviceModel>

Côté serveur, mon fichier web.config contient la section system.serviceModel Suivante:

<system.serviceModel>
    <services>
        <service name="MyService.MyService" behaviorConfiguration="MyService.MyServiceBehaviour" >
            <endpoint address="" binding="wsHttpBinding" bindingConfiguration="MyService.MyServiceBinding" contract="MyService.IMyService">
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="MyService.MyServiceBinding">
          <security mode="None"></security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="MyService.MyServiceBehaviour">
                <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
                <serviceMetadata httpGetEnabled="true"/>
                <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
                <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>

J'ai regardé a assez grandnombre de réponses à cette question avec pas de succès .

Est-ce que quelqu'un peut m'aider avec ça?

74
Damovisa

Essayez également de définir maxReceivedMessageSize sur le serveur, par exemple. à 4MB:

    <binding name="MyService.MyServiceBinding" 
           maxReceivedMessageSize="4194304">

La principale raison pour laquelle la valeur par défaut (65535, je crois) est si faible est la réduction du risque d’attaques par déni de service (DoS). Vous devez définir une taille supérieure à la taille maximale de la demande sur le serveur et à la taille maximale de la réponse sur le client. Si vous vous trouvez dans un environnement Intranet, le risque d'attaques par déni de service est probablement faible. Par conséquent, il est probablement prudent d'utiliser une valeur beaucoup plus élevée que prévu.

Quelques conseils pour résoudre les problèmes de connexion aux services WCF:

  • Activez le traçage sur le serveur comme décrit dans cet article MSDN .

  • Utilisez un outil de débogage HTTP tel que Fiddler sur le client pour inspecter le trafic HTTP.

107
Joe

J'avais aussi ce problème, mais rien de ce qui précède n'a fonctionné pour moi car j'utilisais une liaison personnalisée (pour BinaryXML) après une longue recherche, j'ai trouvé la réponse ici: -

Envoi de fichiers XML volumineux de Silverlight à WCF

Lors de l'utilisation d'un customBinding, maxReceivedMessageSize doit être défini sur l'élément httpTransport sous l'élément de liaison dans le fichier web.config:

<httpsTransport maxReceivedMessageSize="4194304" /> 
7
Mark Davies

Si vous utilisez .NET 4.0, vous devez prendre en compte le fait que si aucun noeud final valide n’est trouvé dans votre configuration, un noeud final par défaut sera automatiquement créé et utilisé.

Le point de terminaison par défaut utilisera toutes les valeurs par défaut. Par conséquent, si vous pensez avoir une configuration de service valide avec une valeur importante pour maxReceivedMessageSize, etc. créé et utilisé.

Ceci est fait en silence, il est donc difficile à détecter. Vous verrez des messages à cet effet (par exemple, "Aucun noeud final trouvé pour le service, créant un noeud final par défaut" ou similaire) si vous activez le traçage sur le serveur mais qu'il n'y a aucune autre indication (à ma connaissance).

7
user469104

Dans le serveur de .NET 4.0 dans web.config, vous devez également modifier la liaison par défaut. Définissez les 3 paramètres suivants:

 < basicHttpBinding>  
   < !--http://www.intertech.com/Blog/post/NET-40-WCF-Default-Bindings.aspx  
    - Enable transfer of large strings with maxBufferSize, maxReceivedMessageSize and maxStringContentLength
    -->  
   < binding **maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"**>  
      < readerQuotas **maxStringContentLength="2147483647"**/>            
   < /binding>
5
RaSor

Vous pouvez également activer la journalisation WCF pour plus d'informations sur l'erreur d'origine. Cela m'a aidé à résoudre ce problème.

Ajoutez ce qui suit à votre web.config, il enregistre le journal dans C:\log\Traces.svclog

<system.diagnostics>
    <sources>
        <source name="System.ServiceModel"
                  switchValue="Information, ActivityTracing"
                  propagateActivity="true">
            <listeners>
                <add name="traceListener"
                     type="System.Diagnostics.XmlWriterTraceListener"
                     initializeData= "c:\log\Traces.svclog" />
            </listeners>
        </source>
    </sources>
</system.diagnostics>
4
Aaron Hoffman

Il peut être utile de déboguer le client, de désactiver Outils\Options\Débogage\Général\'Activer uniquement mon code', de cliquer sur Déboguer\Exceptions\"intercepte toutes les exceptions de la première chance" pour les exceptions CLR gérées, et de voir s’il existe une erreur. exception sous le capot sur le client avant l'exception de protocole et avant que le message ne frappe le fil. (Je pense que ce serait une sorte d'échec de la sérialisation.)

4
Brian

Je veux juste souligner

En plus de MaxRecivedMessageSize, il existe également des attributs dans ReaderQuotas. Vous pouvez atteindre le nombre maximal d'éléments au lieu de la taille. Le lien MSDN est ici

3
Yuan

J'ai trouvé la réponse au problème de la mauvaise demande 400.

C'était le paramètre de liaison de serveur par défaut. Vous devez ajouter aux paramètres par défaut du serveur et du client.

binding name = "" openTimeout = "00:10:00" closeTimeout = "00:10:00" receiveTimeout = "00:10:00" sendTimeout = "00:10:00" maxReceivedMessageSize = "2147483647" maxBufferPoolSize = "2147483647 "maxBufferSize =" 2147483647 ">

3
singh

Dans mon cas, cela ne fonctionnait pas, même après avoir essayé toutes les solutions et défini toutes les limites au maximum. En dernier, j'ai découvert qu'un Microsoft IIS RL Scan 3.1 était installé sur IIS/site Web, qui possède sa propre limite pour rejeter les demandes entrantes en fonction de la taille du contenu et retournez "404 page non trouvée".

Sa limite peut être mise à jour dans %windir%\System32\inetsrv\urlscan\UrlScan.ini fichier en définissant MaxAllowedContentLength à la valeur requise.

Pour par exemple. ce qui suit permettra jusqu'à 300 requêtes de mb

MaxAllowedContentLength = 314572800

J'espère que ça va aider quelqu'un!

1
Sukhdeep Singh