Вопрос по webhttpbinding, rest, request, web-config – Невозможно установить maxReceivedMessageSize через web.config

8

Сейчас я исследовал код 400 - BadRequest за последние два часа. Многие предположения направлены на то, чтобы гарантировать, что атрибут bindingConfiguration установлен правильно, и в моем случае это так.

Теперь мне нужна ВАША помощь, прежде чем разрушать здание, в котором я нахожусь :-)

Я запускаю сервис WCF RestFull (очень легкий, использую этот ресурс для вдохновения:http://msdn.microsoft.com/en-us/magazine/dd315413.aspx) который (на данный момент) принимает XmlElement (POX), предоставляемый через глагол POST.

В настоящее время я использую ТОЛЬКО конструктор запросов Fiddler перед реализацией настоящего клиента (поскольку это смешанная среда).

Когда я делаю это для XML размером менее 65 КБ, он работает нормально - больше, он выдает следующее исключение: превышена квота максимального размера сообщения для входящих сообщений (65536). Чтобы увеличить квоту, используйте свойство MaxReceivedMessageSize в соответствующем элементе привязки.

Вот мой файл web.config (для которого я даже включил тег client (в отчаянные времена!)):

<system.web>
    <httpRuntime maxRequestLength="1500000" executionTimeout="180"/>
  </system.web>
  <system.serviceModel>
    <diagnostics>
      <messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
    </diagnostics>
    <bindings>
      <webHttpBinding>
        <binding name="WebHttpBinding" maxReceivedMessageSize="1500000" maxBufferPoolSize="1500000" maxBufferSize="1500000" closeTimeout="00:03:00" openTimeout="00:03:00" receiveTimeout="00:10:00" sendTimeout="00:03:00">
          <readerQuotas maxStringContentLength="1500000" maxArrayLength="1500000" maxBytesPerRead="1500000" />
          <security mode="None"/>
        </binding>
      </webHttpBinding>
    </bindings>
    <client>
      <endpoint address="" binding="webHttpBinding" bindingConfiguration="WebHttpBinding" contract="Commerce.ICatalogue"/>
    </client>
    <services>
      <service behaviorConfiguration="ServiceBehavior" name="Catalogue">
        <endpoint address="" 
                  behaviorConfiguration="RestFull" 
                  binding="webHttpBinding"
                  bindingConfiguration="WebHttpBinding" 
                  contract="Commerce.ICatalogue" />
        <!-- endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" / -->
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="RestFull">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

Заранее благодарим за любую помощь, ведущую к успешному вызову с> 65K XML ;-)

Ваш Ответ

4   ответа
6

что у меня была та же проблема, но когда я настроил привязку по умолчанию для webHttp, то это сработало:

<bindings>
        <webHttpBinding>
            <binding maxReceivedMessageSize="2000000"
                      maxBufferSize="2000000">
                <readerQuotas maxStringContentLength="2000000"/>
            </binding>
        </webHttpBinding>
    </bindings>

Обратите внимание: на привязке нет имени.

Это прекрасно работает, если вы используете System.ServiceModel.Activation.WebServiceHostFactory. ROFLwTIME
0

которую я написал, которая воспроизводит эту проблему с абсолютно минимальной частью сервера и клиента WCF:

WCF - Исправление исключений длины строки на стороне клиента

В частности, вам может понадобиться пользовательская конфигурация привязки. По крайней мере, воспроизведение этого образца может дать вам некоторые идеи для вашей конкретной ситуации.

Таким образом, он работает нормально, используя командную строку или другую клиентскую программу .NET? Я бы не знал, как настроить Fiddler, но если вы убедились, что ваша серверная сторона может обрабатывать> 65k, проблема определенно на стороне Fiddler. Michael Maddox
Проблема в том, что это простая и легкая реализация WCF, использующая класс WebServiceHostFactory. Насколько я понимаю, это означает, что я не могу "Добавить ссылку на службу", потому что для этого требуется формат WSDL (почему я не продолжил с вашей отличной ссылкой). gimlichael
Привет Майкл, Спасибо за ваш вклад. Несмотря на то, что ваша статья интересна, моя задача пока состоит в том, чтобы заставить ее работать с Fiddler. Я предполагаю, что fiddler.config не существует, поэтому у меня нет настроек клиента, которые не должны иметь значения, поскольку я совершенно уверен, что Fiddler не имеет ограничений. Я здесь не прав? gimlichael
Попробуйте переименовать вашу привязку из WebHttpBinding в WebHttpBindingConfiguration, а затем обновите конечную точку, чтобы использовать новое имя. Смотрите также шаг 3 здесь:msdn.microsoft.com/en-us/library/ms733051.aspx , Я не знаю, решит ли это проблему, но это определенно вызывает у меня головную боль. :) Michael Maddox
Я нашел проблему; После тщательного исследования и отсутствия хороших ответов в сети я переосмыслил реализацию в отношении WebServiceHostFactory. Так как это можно использовать БЕЗ записи конфигурации ServiceModel, я сомневаюсь, что она когда-либо читает из нее. Поэтому я изменил реализацию и запишу это в этой ветке, чтобы другие разочарованные, как я, могли быстро найти решение. Спасибо за вашу помощь, хотя :-) gimlichael
6

Так или иначе...

Что я сделал, чтобы решить эту «проблему», я создал фабрику, унаследованную от WebServiceHostFactory, и создал узел пользовательских служб, унаследованный от WebServiceHost

И в хосте я переопределил метод OnOpening, как это

protected override void OnOpening()
        {
            base.OnOpening();

            foreach (var endpoint in Description.Endpoints)
            {
                var binding = endpoint.Binding as System.ServiceModel.Channels.CustomBinding;

                foreach (var element in binding.Elements)
                {
                    var httpElement = element as System.ServiceModel.Channels.HttpTransportBindingElement;
                    if (httpElement != null)
                    {
                        httpElement.MaxBufferSize = 2147483647;
                        httpElement.MaxReceivedMessageSize = 2147483647;
                    }
                }
            }

        }
Потрясающие!!! Спасибо! zdrsh
Это было очень полезно. Я использовал это в среде SharePoint, где я не мог контролировать web.config для службы. MgSam
Для службы MultipleBaseAddressWebServiceHost: foreach (конечная точка var в this.Description.Endpoints) {var binding = endpoint.Binding as System.ServiceModel.WebHttpBinding; binding.MaxReceivedMessageSize = int.MaxValue; } devi
Это скалы! Примечание: не используйте CreateBindings (), чтобы получить привязку, она не будет работать. Используйте приведение, как указано выше. Также обратите внимание на использование определенных фабрик. CCondron
13

этот действительно вызвал у меня трудности с разрешением проблем, ради которых я пощадлю других. Проблема заключалась в том, что я использовал<%@ ServiceHost Factory="System.ServiceModel.Activation.WebServiceHostFactory" Service="fullyQualifiedClassName" %>, который является хорошим и простым подходом к реализации на заводе.

Однако у этого подхода есть свои недостатки; поскольку в файле web.config не требуется настройка, класс WebServiceHostFactory по своему дизайну никогда не считывает данные из файла web.config. Я знаю; Я мог бы унаследовать от этого класса и внести соответствующие изменения, чтобы он действительно мог читать из файла конфигурации, но это казалось немного за рамками.

Моим решением было вернуться к более традиционному способу реализации WCF;<%@ ServiceHost Service="fullyQualifiedClassName" CodeBehind="~/App_Code/Catalogue.cs" %>, а затем используйте мои уже настроенные значения в файле web.config.

Вот мой измененный файл web.config (в отношении головной боли Maddox):

<system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="XmlMessageBinding" maxReceivedMessageSize="5000000" maxBufferPoolSize="5000000" maxBufferSize="5000000" closeTimeout="00:03:00" openTimeout="00:03:00" receiveTimeout="00:10:00" sendTimeout="00:03:00">
          <readerQuotas maxStringContentLength="5000000" maxArrayLength="5000000" maxBytesPerRead="5000000" />
          <security mode="None"/>
        </binding>
      </webHttpBinding>
    </bindings>
    <services>
      <service name="fullyQualifiedClassName" behaviorConfiguration="DevelopmentBehavior">
        <endpoint name="REST" address="" binding="webHttpBinding" contract="fullyQualifiedInterfaceName" behaviorConfiguration="RestEndpointBehavior" bindingConfiguration="XmlMessageBinding" />
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="RestEndpointBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="DevelopmentBehavior">
          <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
        <behavior name="ProductionBehavior">
          <serviceDebug httpHelpPageEnabled="false" includeExceptionDetailInFaults="false"/>
          <serviceMetadata httpGetEnabled="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

Еще одно преимущество этого изменения заключается в том, что теперь вы можете ссылаться на службу WCF-отдыха напрямую из .NET; это не может быть сделано с использованием модели Factory и моей реализации XmlElement через решение.

Я надеюсь, что это может помочь другим с похожими проблемами ...

Upvote, потому что это поведение на самом деле неясно, и вывод о том, что ServiceRoutes не использует привязки из Web.Config, похоже, нигде не документирован, но определенно имеет место. Scott Chamberlin
У меня была та же проблема, и я подумал, что это может быть Фабрика, спасибо, что подтвердил это для меня. Alex

Похожие вопросы