WCF - 如何增加消息大小配额

493

我有一个返回1000条记录的WCF服务,从数据库中向客户端返回数据。我有一个ASP.NET WCF客户端(我已经在ASP.NET Web应用程序项目中添加了服务引用以使用WCF)。

当我运行客户端应用程序时,会收到以下消息:

传入消息的最大消息大小配额(65536)已超过。要增加配额,请在适当的绑定元素上使用MaxReceivedMessageSize属性。

如何增加消息大小配额?需要什么帮助吗?


1
我曾经遇到过同样的问题,但是我只是收到了一个不友好的网络错误400,但解决方案是消息大小的问题。 - Mr W
2
我通过使用链接中提到的步骤解决了这个问题。 - Ram
为什么默认设置这么低?安全因素吗? - Paul C
@Coops确实是为了安全。例如,通过设置消息配额,DDOS攻击就会变得更加困难(至少有点)。 - Peter van Kekem
只需要在服务器端更新您的配置。 - AbbathCL
13个回答

649

你需要像这样去增加消息大小的配额,在App.config或者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>

在您的终端配置中使用绑定名称,例如:

...
bindingConfiguration="basicHttp"
...

这些值的理由很简单,它们足够大以容纳大多数消息。您可以调整该数字以适应自己的需求。低默认值基本上是为了防止DOS类型攻击。将其设置为20000000会使分布式DOS攻击变得有效,而64k的默认大小需要非常多的客户端才能压倒大多数服务器。


22
谢谢。这个更改需要在客户应用程序的web.config文件中进行。 - bugBurger
8
如果你需要将一个大的数据集作为参数传递给 WCF 方法,那么你可能还需要在服务器上进行更改。 - Nate
9
它足够大,能容纳大多数信息。您可以根据需要调整该数字。它的基本作用是防止DOS攻击。将其设为20000000会使分布式DOS攻击变得有效,而默认大小为64k现在需要非常多的客户端才能克服大多数服务器。 - Nate
19
对于其他感兴趣的人,我在另一个博客上读到的是最大尺寸为2147483647。20000000比这个数字小一些,因此使用可以不中断服务的最小数字是有意义的。 - proudgeekdad
5
如果传入参数太大,就需要在服务器上进行更改;否则(更可能的情况是),需要在客户端配置文件中进行更改,因为服务的响应(而不是其参数)过大。 - Nate
显示剩余18条评论

167

如果您在使用WCF测试客户端时仍然收到此错误消息,那是因为客户端有单独的MaxBufferSize设置。

要纠正此问题:

  1. 右键单击树底部的Config File节点
  2. 选择使用SvcConfigEditor进行编辑

将显示可编辑的设置列表,包括MaxBufferSize。

注意:自动生成的代理客户端也默认将MaxBufferSize设置为65536。


8
为什么我总是会忘记这件事?+1 - James Skemp
9
在VS2013中,SvcConfigEditor被替换为“编辑WCF配置”,如果有人在寻找它。 - ZoomVirus
无法找到SVCconfigEditor? - Arul Sidthan
你会在Bindings文件夹下找到它,点击服务的绑定,它就在里面。 - Sameer Alibhai
如果你的配置文件是自动生成的,那么你绝对应该这样做。任何时候你更新了你的参考资料,它将重新生成 app.config,然后你就必须手动再次更改它。但如果你在 VS 中更改它,新的更改将适应你所选择的设置。 - kingfrito_5005
1
我必须在同一部分下面设置ReaderQuotas属性。 - Asad Naeem

118

如果你正在动态创建你的WCF绑定,这里是代码:

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

你可以使用它进行初始化。显然,你可以在构造方法中使用它。 - aemre
2
10年后,我又需要这个了,真希望我能点赞两次。 - Erçin Dedeoğlu

49

WCF测试客户端有自己的客户端配置文件。

运行测试客户端并向下滚动。如果您双击“配置文件”节点,您将看到XML表示形式。正如您所见,maxReceivedMessageSize65536

要进行编辑,请右键单击“配置文件”树节点,然后选择使用SvcConfigEditor进行编辑。当编辑器打开时,展开绑定并双击自动生成的绑定。

您可以在此处编辑所有属性,包括maxReceivedMessageSize。完成后,单击“文件 - 保存”。

最后,当您回到WCF测试客户端窗口时,单击“工具 - 选项”。

注意取消选中“启动服务时总是重新生成配置”


2
这可能是这里最好的答案! - Haris
3
因为注意事项提到了取消勾选“总是重新生成配置”选项,所以点赞。 - furier
在我看来,这是最简单的解决方法。帮我省了不少麻烦。 - Jared Beach
在vs2013中,如果有人正在寻找SvcConfigEditor,则应该使用Edit WCF configuration进行替换。 - ZoomVirus
谢谢。我已经为此烦恼了一段时间,一遍又一遍地更改服务器配置,而问题却出在测试客户端配置上! - Fahad
如果我将maxReceivedMessageSize更改为100,000,然后刷新服务,在取消选中您在备注中写的内容之后,它仍然显示接收到的消息大小超过65536。看起来好像我无法更改大小,即使我正确保存了它。 - dezox

25

我找到了一种简单的方法

--- 右键单击webconfig或app config文件,点击“编辑WCF配置”,然后转到bingdigs并选择您的服务,在右侧显示的maxReciveMessageSize中输入一个较大的数字 ---


2
这是一个很好的答案,我不知道我可以从这里进行编辑,谢谢。 - albert sh

8

我解决问题的方法如下:

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

21
与我的解决方案相比,这有何不同之处?除了你包括配置中所有无关部分和相关部分外,你选择的是最大可能值,而我选择的是200米? - Nate
4
上下文也很重要,也许这两个答案可以合并吗? - Jeff
1
这个设置应该在服务器端还是客户端进行配置? - John Kenedy

8

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

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

重要提示:

如果您尝试传递具有许多连接对象(例如:树形数据结构,包含许多对象的列表...)的复杂对象,则无论您如何增加配额,通信都将失败。 在这种情况下,您必须增加包含对象的数量:

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

maxItemsInObjectGraph 对我来说是一个(快速)解决方案。但是当增加它时,您应该考虑是否更好的解决方案是让您的应用程序以块的形式请求数据,而不是一个可能会耗尽资源的巨大对象图。 - Paul

8
我用CalculateRoute()解决了我的项目中Bing Maps WPF的问题。在我的情况下,解决方案是为“customBinding”部分的“httpTransport”属性设置maxReceivedMessageSize和maxReceivedMessageSize。
我在应用程序配置文件(例如myApp.config)中设置了以下配置:
<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>

8

这非常有用,但理论上是否有其他选择? - Gabriele D'Onufrio
很遗憾,我没有找到任何替代方案。 - Valerio Gentile

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>


非常适合发布您的答案。重要的是,“bindingConfiguration”值与绑定名称匹配。在您的示例中为“wsHttpBinding_Username”。 - Bruno Bieri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接