解決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);

當然,在生產應用程序中,我將確保存在此類程序化替代活動的日誌(可審覈事件)。我可能還會考慮向用戶提出建議,要求給軟件提供自動更正值的機會(例如,更新有效的應用程序配置文件)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章