Помилка великого запиту веб-служби WCF із помилковим запитом HTTP (400)


74

Я зіткнувся з цією очевидно поширеною проблемою і не зміг її вирішити.

Якщо я зателефоную до своєї веб-служби WCF із відносно невеликою кількістю елементів у параметрі масиву (я протестував до 50), все в порядку.

Однак, якщо я зателефоную до веб-служби з 500 елементами, я отримую помилку Bad Request.

Цікаво, що я запустив Wireshark на сервері, і, схоже, запит навіть не потрапляє на сервер - помилка 400 генерується на стороні клієнта.

Винятком є:

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.

system.serviceModelЧастина мого файлу конфігурації клієнта є:

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

На стороні сервера мій файл web.config має такий system.serviceModelрозділ:

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

Я подивився на на досить великій кількості з відповідей на це питання з не увінчалися успіхом .

Хто-небудь може мені допомогти в цьому?


Якщо це не потрапляє на сервер, можливо, щось не так із переданими даними. Можливо, в запиті є якісь нелегальні символи? Також припускаючи, що це SOAP
Чад Грант

1
Отже, ви спробували встановити всі атрибути max (наприклад, maxReceivedMessageSize ...) на дійсно велике число?
південь

Так, це SOAP. І в запиті не повинно бути нічого поганого - як я вже говорив, все працює нормально для до 50 елементів, що генеруються з тим самим додатком ...
Damovisa

@mundeep - так - я спробував встановити для них усі значення 2147483647, але там не пощастило. Деякі сторінки, на які я
посилався,

Відповіді:


107

Спробуйте також встановити maxReceivedMessageSize на сервері, наприклад, до 4 МБ:

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

Основна причина, за якою за замовчуванням (65535, на мою думку), є настільки низькою - це зменшення ризику атак відмови в обслуговуванні (DoS). Вам потрібно встановити його більше, ніж максимальний розмір запиту на сервері та максимальний розмір відповіді на клієнті. Якщо ви перебуваєте в середовищі Інтранет, ризик атак DoS, ймовірно, низький, тому, ймовірно, безпечно використовувати значення набагато вище, ніж ви очікуєте.

До речі, кілька порад щодо усунення неполадок підключення до служб WCF:

  • Увімкніть трасування на сервері, як описано в цій статті MSDN .

  • Використовуйте інструмент налагодження HTTP, такий як Fiddler на клієнті, щоб перевірити HTTP-трафік.


1
Дивно - це все, що було. Дякую за вашу відповідь!
Damovisa

2
Дякуємо за посилання, щоб увімкнути відстеження!
Колін Десмонд,

2
Я намагався зробити те саме в своєму кінці, але не міг відчути смак успіху.
Кангкан

1
Корисна публікація в блозі: geekswithblogs.net/smyers/archive/2011/10/05/… - Я просто хочу зазначити людям, які читають цю відповідь, що наведений вище фрагмент коду у відповіді повинен перейти до розділу прив'язок вашого прив'язки. Приклад: Нехай прив'язка буде базовоюHttpBinding: <bindings> <basicHttpBinding> <binding ... /> <readerQuotas ... /> </basicHttpBinding> </bindings> - також може містити <readerQuotas maxArrayLength = "" /> бути встановленим (мені довелося).
dislexicanaboko

7

Я також отримував цю проблему, однак жодне з перерахованого не працювало для мене, оскільки я використовував спеціальне прив'язування (для BinaryXML) після довгого копання, я знайшов тут відповідь: -

Надсилання великого XML із Silverlight на WCF

Як я використовую customBinding, maxReceivedMessageSize повинен бути встановлений для елемента httpTransport під елементом прив'язки в web.config:

<httpsTransport maxReceivedMessageSize="4194304" /> 

7

Для того, що це варто, додатковою міркуванням при використанні .NET 4.0 є те, що якщо у вашій конфігурації не знайдено дійсної кінцевої точки, кінцева точка за замовчуванням буде автоматично створена та використана.

Кінцева точка за замовчуванням використовуватиме всі значення за замовчуванням, тому, якщо ви вважаєте, що у вас є діюча конфігурація служби з великим значенням для maxReceivedMessageSize тощо, але з конфігурацією щось не так, ви все одно отримаєте 400 Поганих запитів, оскільки кінцевою точкою за замовчуванням буде створені та використані.

Це робиться мовчки, тому важко виявити. Ви побачите відповідні повідомлення (наприклад, "Кінцеву точку не знайдено для служби, створення кінцевої точки за замовчуванням" або подібну), якщо ви ввімкнули трасування на сервері, але іншої індикації (наскільки мені відомо) немає.


@ user469104: Дуже хороша порада. Дякую. Чи є спосіб змусити сервер використовувати заявлену вручну кінцеву точку без перезапису за замовчуванням ServiceHost?
RaSor

5

На сервері в .NET 4.0 у web.config вам також потрібно змінити прив'язку за замовчуванням. Встановіть наступні 3 парми:

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

4

Може бути корисно налагодити клієнта, вимкнути Інструменти \ Параметри \ Налагодження \ Загальне \ 'Увімкнути лише мій код', клацнути Налагодження \ Винятки \ 'вловити всі винятки першої можливості' для керованих винятків CLR і перевірити, чи є виняток під капотом на клієнті перед винятком протоколу та до того, як повідомлення потрапить у провід. (На мою думку, це була б якась помилка серіалізації.)


4

Ви також можете увімкнути ведення журналу WCF для отримання додаткової інформації про вихідну помилку. Це допомогло мені вирішити цю проблему.

Додайте до веб-файлу web.config таке, що зберігає журнал у 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>

1
Іноді найпростіші відповіді є найкращими. Для мене я виявив, що повертаю нульовий об’єкт Stream під час виклику потокової відповіді. Svclog вирішив це за лічені секунди. Дякую.
Сенатор,

3

Просто хочу вказати

Окрім MaxRecivedMessageSize, в ReaderQuotas також є атрибути, ви можете натиснути обмеження кількості елементів замість обмеження розміру. Посилання MSDN тут


3

Я знайшов відповідь на проблему Bad Request 400.

Це було налаштування прив’язки сервера за замовчуванням. Вам потрібно буде додати до сервера та клієнта налаштування за замовчуванням.

ім'я прив'язки = "" openTimeout = "00:10:00" closeTimeout = "00:10:00" receiveTimeout = "00:10:00" sendTimeout = "00:10:00" maxReceivedMessageSize = "2147483647" maxBufferPoolSize = "2147483647 "maxBufferSize =" 2147483647 ">


1

У моєму випадку це не спрацювало навіть після випробування всіх рішень та встановлення всіх обмежень на макс. Нарешті я дізнався, що модуль фільтрації Microsoft IIS Url Scan 3.1 на IIS / веб-сайті встановлений , який має власне обмеження для відхилення вхідних запитів на основі розміру вмісту та повернення "404 Не знайдена сторінка".

Це обмеження можна оновити у %windir%\System32\inetsrv\urlscan\UrlScan.iniфайлі, встановившиMaxAllowedContentLength необхідне значення.

Наприклад, наступне дозволить до 300 Мб запитів

MaxAllowedContentLength = 314572800

Сподіваюся, це комусь допоможе!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.