WCF - Jak zwiększyć limit rozmiaru wiadomości

453

Mam usługę WCF, która zwraca 1000 rekordów z bazy danych do klienta. Mam klienta WCF ASP.NET (dodałem odniesienie do usługi w projekcie aplikacji sieci web asp.net, aby korzystać z WCF).

Po uruchomieniu aplikacji klienckiej pojawia się następujący komunikat:

Limit maksymalnej wielkości wiadomości dla wiadomości przychodzących (65536) został przekroczony. Aby zwiększyć przydział, użyj właściwości MaxReceivedMessageSize na odpowiednim elemencie wiążącym.

Jakaś pomoc? Jak zwiększyć limit rozmiaru wiadomości?

bugBurger
źródło
Miałem ten sam problem, ale właśnie dostałem nieprzyjazny błąd sieci 400, ale rozwiązaniem było coś takiego jak rozmiar wiadomości.
Pan W
2
Rozwiązałem problem, wykonując kroki wymienione w [link] [1] [1]: stackoverflow.com/questions/7476853/…
Ram
Dlaczego domyślnie jest tak niski? Bezpieczeństwo?
Coops
@ Coo dla bezpieczeństwa. Ustawiając przydział dla wiadomości, na przykład ataki DDOS są (przynajmniej trochę) trudniejsze do wykonania.
Peter van Kekem

Odpowiedzi:

607

Potrzebujesz czegoś takiego, aby zwiększyć limity wielkości wiadomości w pliku App.config lub 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>

I użyj nazwy powiązania w konfiguracji punktu końcowego, np

...
bindingConfiguration="basicHttp"
...

Uzasadnienie wartości jest proste, są one wystarczająco duże, aby pomieścić większość komunikatów. Możesz dostroić ten numer do swoich potrzeb. Niska wartość domyślna ma zasadniczo zapobiegać atakom typu DOS. Ustawienie 20000000 pozwoliłoby na skuteczność rozproszonego ataku DOS, domyślny rozmiar 64k wymagałby bardzo dużej liczby klientów, aby obezwładnić większość serwerów w dzisiejszych czasach.

Nate
źródło
20
Dzięki .. Tej zmiany należy dokonać w pliku web.config aplikacji klienckiej.
bugBurger
8
Konieczna może być również zmiana na serwerze - w przypadku, gdy musisz wysłać duży zestaw danych jako parametr do metody WCF.
Nate
9
Jest wystarczająco duży, aby pomieścić większość wiadomości. Możesz dostroić ten numer do swoich potrzeb. Zasadniczo służy to zapobieganiu atakom typu DOS. Ustawienie 20000000 pozwoliłoby na skuteczność rozproszonego ataku DOS, domyślny rozmiar 64k wymagałby bardzo dużej liczby klientów, aby obezwładnić większość serwerów w dzisiejszych czasach.
Nate
18
Dla innych, którzy są zainteresowani, przeczytałem na innym blogu, że maksymalny rozmiar to 2147483647. 20000000 jest nieco mniejszy od tej liczby, więc użycie najmniejszej liczby, z której można uciec bez przerywania usługi, ma sens.
dumnyekekad
5
@Slauma Musiałoby zostać zmienione na serwerze, jeśli ten przychodzący parametr był zbyt duży; w przeciwnym razie (i bardziej prawdopodobne) zmiany należy dokonać w pliku konfiguracyjnym klienta, ponieważ odpowiedź usługi (a nie jej parametr) jest zbyt duża.
Nate
155

Jeśli nadal pojawia się ten komunikat o błędzie podczas korzystania z klienta testowego WCF, to dlatego, że klient ma osobny MaxBufferSize ustawienie .

Aby rozwiązać problem:

  1. Kliknij prawym przyciskiem myszy plik konfiguracji węzeł konfiguracji na dole drzewa
  2. Wybierz Edytuj za pomocą SvcConfigEditor

Pojawi się lista edytowalnych ustawień, w tym MaxBufferSize.

Uwaga: Automatycznie generowani klienci proxy również domyślnie ustawiają MaxBufferSize na 65536.

Michael Rodrigues
źródło
8
Dlaczego och, dlaczego zawsze o tym zapominam? +1
James Skemp,
9
W vs2013 SvcConfigEditor jest zastępowany przez Edytuj konfigurację WCF, jeśli ludzie go szukają.
ZoomVirus,
Nie możesz znaleźć SVCconfigEditor?
Arul Sidthan,
Znajdziesz go w folderze Wiązania, kliknij powiązanie dla usługi i tam jest.
Sameer Alibhai,
Jeśli plik konfiguracyjny jest generowany automatycznie, absolutnie powinieneś to zrobić w ten sposób. Za każdym razem, gdy zaktualizujesz referencję, zostanie ponownie wygenerowany plik app.config i będziesz musiał ręcznie go zmienić ponownie. Jeśli zmienisz go VS, nowe zmiany uwzględnią wybrane ustawienia.
kingfrito_5005
104

Jeśli dynamicznie tworzysz powiązania WCF, oto kod do użycia:

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.
źródło
Możesz go zainicjować. Oczywiście możesz użyć go jako metody konstruktora.
aemre
45

WCF test klienta ma swój własny config klienta.

Uruchom klienta testowego i przewiń w dół. Po dwukrotnym kliknięciu węzła Plik konfiguracji zobaczysz reprezentację XML. Jak widać, maxReceivedMessageSizejest65536 .

Aby go edytować, kliknij prawym przyciskiem myszy węzeł drzewa Plik konfiguracji i wybierz opcję Edytuj za pomocą SvcConfigEditor . Po otwarciu edytora rozwiń Wiązania i kliknij dwukrotnie powiązanie, które zostało automatycznie wygenerowane.

Możesz edytować wszystkie właściwości tutaj, w tym maxReceivedMessageSize. Po zakończeniu kliknij Plik - Zapisz .

Na koniec, gdy wrócisz do okna klienta testowego WCF, kliknij Narzędzia - Opcje .

UWAGA : Usuń zaznaczenie opcji Zawsze generuj ponownie konfigurację podczas uruchamiania usług .

Jodee Dex Page
źródło
2
Prawdopodobnie najlepsza odpowiedź tutaj!
Haris
3
upvote ze względu na notatkę, aby odznaczyć Always regenerate configopcję.
furier
Najprostsze rozwiązanie moim zdaniem. Uratowało mnie trochę bólu głowy.
Jared Beach
W vs2013 SvcConfigEditor jest zastępowany przez Edytuj konfigurację WCF, jeśli ludzie go szukają.
ZoomVirus,
Dziękuję Ci. Przez chwilę łamałem sobie głowę, ciągle zmieniając konfigurację serwera, gdy problem dotyczył konfiguracji klienta testowego!
Fahad,
24

Znalazłem łatwy sposób

--- kliknij prawym przyciskiem myszy plik konfiguracyjny webconfig lub aplikacji i kliknij EDYTUJ KONFIGURACJĘ WCF i przejdź do bingdigs i wybierz poprzednią usługę, a po prawej stronie pokaż maxReciveMessageSize podaj dużą liczbę ---

NC64
źródło
2
To była świetna odpowiedź, nie wiedziałem, że mogę stąd edytować, dzięki
Albert Sh
8

Rozwiązuję problem ... w następujący sposób

    <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
źródło
20
Czym różni się to od mojego rozwiązania? Poza tym, że podałeś wszystkie nieistotne części swojej konfiguracji, a także odpowiednie części, a Ty wybrałeś maksymalną możliwą wartość zamiast 200m, którą wybrałem?
Nate
3
Kontekst też jest dobry ... może te dwie odpowiedzi można połączyć?
Jeff
1
czy to ustawienie należy skonfigurować na serwerze czy kliencie?
John Kenedy,
8

Rozwiązałem swój problem na Bing Maps WPF w moim projekcie za pomocą CalculateRoute (). Rozwiązaniem w moim przypadku było ustawienie maxReceivedMessageSize i maxReceivedMessageSize dla atrybutu „httpTransport” dla sekcji „customBinding”.

W pliku Applications.config (np. MyApp.config) ustawiłem następującą konfigurację:

<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
źródło
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
źródło
Idealne do opublikowania odpowiedzi. Ważne jest, aby wartość „bindingConfiguration” była zgodna z nazwą wiązania. W twoim przykładzie „wsHttpBinding_Username”.
Bruno Bieri,
6

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

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

WAŻNY:

Jeśli spróbujesz przekazać złożony obiekt, który ma wiele połączonych obiektów (np. Strukturę danych drzewa, listę zawierającą wiele obiektów ...), komunikacja nie powiedzie się bez względu na to, jak zwiększysz przydziały. W takich przypadkach należy zwiększyć liczbę obiektów zawierających:

<behaviors>
  <serviceBehaviors>
    <behavior name="NewBehavior">
      ...
      <dataContractSerializer maxItemsInObjectGraph="2147483646"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
Jakub
źródło
To maxItemsInObjectGraphbyło (szybkie) rozwiązanie dla mnie. Ale zwiększając to, powinieneś pomyśleć o tym, czy lepszym rozwiązaniem jest, aby aplikacja żądała danych w porcjach, w przeciwieństwie do ogromnego wykresu obiektowego, który może obciążać zasoby.
Paul
6

Dla mnie wszystko, co musiałem zrobić, to dodać maxReceivedMessageSize="2147483647"do klienta app.config. Serwer pozostał nietknięty.

Ashilon
źródło
5

Kolejna ważna rzecz do rozważenia z mojego doświadczenia ...

Zdecydowanie odradzam maksymalizowanie maxBufferPoolSize, ponieważ bufory z puli nigdy nie są zwalniane, dopóki domena aplikacji (tj. Pula aplikacji) nie zostanie zrestartowana.

Okres dużego ruchu może spowodować, że pamięć będzie używana i nigdy nie zostanie zwolniona.

Więcej informacji tutaj:

Valerio Gentile
źródło
3

Nie zapominaj, że pod uwagę zostanie wzięty app.config punktu wejścia wykonania, a nie ten w projekcie biblioteki klas zarządzającym wywołaniami usługi sieciowej, jeśli taki istnieje.

Na przykład jeśli pojawi się błąd podczas uruchamiania testu jednostkowego, musisz skonfigurować odpowiednią konfigurację w projekcie testowym.

Gadanina
źródło
0

dostałem ten błąd podczas korzystania z tych ustawień w pliku web.config

System.ServiceModel.ServiceActivationException

ustawiam takie ustawienia:

      <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
źródło
4
Więc rozwiązałeś problem, korzystając z odpowiedzi Nate'a, a następnie opublikowałeś ją jako własną. Nie fajnie.
arcain
@arcain Nates odpowiedź była bardzo ogólna, wykorzystując nazwy i numery akcji, których często można się spodziewać. Ta odpowiedź nie została skradziona, to po prostu właściwa odpowiedź. Ponieważ jest tylko jedna poprawna odpowiedź, musiała zostać powtórzona.
kingfrito_5005
@ kingfrito_5005 „Prawidłowa” odpowiedź była już dostępna, gdy odpowiadający ją opublikował. Całkiem wyraźnie podniósł bindingsżywioł Nate'a i umieścił go jako część swojej odpowiedzi. Te 2000000wartości są dość wyraźne.
arcain
@arcain, nie zgadzam się, że są to bardzo standardowe wartości, moja firma wykorzystuje je również w naszych elementach wiążących.
kingfrito_5005