解决MaxReceivedMessageSize问题

如果您是企业内容服务的基于.NET的使用者(例如,通过Documentum Foundation Services提供的那些),并且遇到与MaxReceivedMessageSize有关的Windows Communication Foundation CommunicationException,则您可能会对本文的详细信息感兴趣。这篇文章既适用于直接面向WSDL的消费者,也适用于利用DFS生产力层的.NET的消费者。一般而言,本文的指南与WCF有关;但是,它将在ECS / DFS上下文中提供。

根据从服务到应用程序的传入消息的大小,您可能会发现需要增加最大接收消息大小。例如,您的应用程序遇到WCF引发的以下异常:

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

超出配额的一个例子是应用程序请求,该请求会导致基于数据包的响应,其中包含大量数据对象和/或一组具有重要元数据和/或内容的数据对象(例如ObjectService.get)。

如果使用Visual Studio和WCF的“添加服务参考”设计器实现此服务的直接指向WSDL的使用者,则默认情况下,您将在整体解决方案中引入每个服务绑定应用程序配置文件。因此,要声明性地增加最大接收消息大小,您将编辑app.config,方法是着重于从配置中的默认值增加适当的(命名)绑定元素上的MaxReceivedMessageSize属性的值,如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="ObjectServicePortBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
        . . .
      </basicHttpBinding>
    </bindings>
    . . .
  </system.serviceModel>
  . . .
</configuration>

与直接面向WSDL的使用者一样,DFS对象服务的基于生产力层的使用者也可能需要声明性地增加MaxReceivedMessageSize的值,使其与实际的运行时要求更加兼容。

在本地DFS SDK的etc \ config目录路径中,您应该找到一个示例App.config文件。请注意,此app.config文件面向生产力层使用者,而不是通过WCF直接指向WSDL使用者。话虽如此,相同的绑定属性也适用于此处的解决方案。区别在于如何在app.config中声明绑定。

面向生产力层的声明将单个绑定DfsDefaultService命名为充当所有DFS服务的绑定,但DFS运行时服务除外,它们已声明了单独的命名绑定。因此,对象服务从“ DfsDefaultService”绑定中获取其(基于WCF的)绑定配置……例如,查询服务也是如此。

要在面向生产力层的app.config中声明性地增加最大接收消息大小,您很可能会从配置中的默认值编辑“ DfsDefaultService”绑定元素上的MaxReceivedMessageSize属性,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  . . .
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        . . .
        <binding name="DfsDefaultService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="1000000" maxBufferPoolSize="10000000" maxReceivedMessageSize="1000000" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
  </system.serviceModel>

您可能会注意到,基于DFS SDK的app.config绑定元素属性值不同于直接从WCF的默认值(即maxBufferSize–1000000与65536,maxBufferPoolSize–1000000与524288,以及maxReceivedMessageSize–1000000与65536)。这只是一个更改,目的是减少遇到与MaxReceivedMessageSize值有关的WCF CommunicationExceptions的可能性。

您可以采用一种确定应用程序合理的MaxReceivedMessageSize值的技术,是将绑定属性/属性的值设置为绝对最大值,以便使用Web调试代理(如CharlesFiddler)来描述实际的运行时消息大小。也就是说,暂时将MaxReceivedMessageSize设置为2147483647(即Int32.MaxValue),通过端口转发将您的SOAP消息通过例如Charles传递,查看响应消息的内容长度值,并相应地重置默认的运行时MaxReceivedMessageSize值。

如果您希望对应用程序的WCF绑定配置采用声明式方法,但是您担心用户将值设置得太低,则始终可以在运行时询问值,以确保它们足够。

例如,基于生产力层的客户端可以执行以下操作:

System.Reflection.FieldInfo appConfigInfo = typeof(ContextFactory).GetField("appConfig", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
System.Reflection.FieldInfo agentServiceBindingInfo = typeof(AppConfig).GetField("m_agentServiceBinding", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
System.Reflection.FieldInfo contextRegistryServiceBindingInfo = typeof(AppConfig).GetField("m_contextRegistryServiceBinding", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
System.Reflection.FieldInfo defaultServiceBindingInfo = typeof(AppConfig).GetField("m_defaultServiceBinding", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
BasicHttpBinding binding = new BasicHttpBinding();
binding.MaxReceivedMessageSize = 0x7fffffffL;
binding.MaxBufferSize = 0x7fffffffL;
agentServiceBindingInfo.SetValue(appConfigInfo.GetValue(contextFactory), binding);
contextRegistryServiceBindingInfo.SetValue(appConfigInfo.GetValue(contextFactory), binding);
defaultServiceBindingInfo.SetValue(appConfigInfo.GetValue(contextFactory), binding);

当然,在生产应用程序中,我将确保存在此类程序化替代活动的日志(可审核事件)。我可能还会考虑向用户提出建议,要求给软件提供自动更正值的机会(例如,更新有效的应用程序配置文件)。

猜你喜欢

转载自blog.csdn.net/qq_28368039/article/details/106994649