【问题标题】:WCF - The maximum nametable character count quota (16384) has been exceeded while reading XML dataWCF - 读取 XML 数据时已超出最大可命名字符计数配额 (16384)
【发布时间】:2011-02-15 11:22:38
【问题描述】:

我有一个使用 wsHttpBinding 的 WCF 服务。服务器配置如下:

<bindings>
      <wsHttpBinding>
        <binding name="wsHttpBinding" maxBufferPoolSize="2147483647"
          maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
            maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
          <security mode="None">
            <transport clientCredentialType="Windows" proxyCredentialType="None"
              realm="" />
            <message clientCredentialType="Windows" negotiateServiceCredential="true"
              algorithmSuite="Default" establishSecurityContext="true" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>

在客户端,我包含了 WCF 服务的服务引用。如果我的 IService 中的功能有限,比如 90 操作合同,但如果添加一个操作合同而不是我无法更新服务引用,我也无法添加该服务引用,它会很好用。在this 文章中提到,通过更改这些配置文件(即 devenv.exe.config、WcfTestClient.exe.config 和 SvcUtil.exe.config)它可以工作,但即使在这些配置文件中包含这些绑定仍然会弹出错误说

下载“http://10.0.3.112/MyService/Service1.svc/mex”时出错。 请求失败,HTTP 状态为 400:错误请求。 元数据包含无法解析的引用:“http://10.0.3.112/MyService/Service1.svc/mex”。 XML 文档中存在错误 (1, 89549)。 读取 XML 数据时已超出最大可命名字符计数配额 (16384)。 nametable 是一种数据结构,用于存储在 XML 处理过程中遇到的字符串 - 具有不重复元素名称、属性名称和属性值的长 XML 文档可能会触发此配额。通过更改创建 XML 阅读器时使用的 XmlDictionaryReaderQuotas 对象的 MaxNameTableCharCount 属性,可以增加此配额。第 1 行,位置 89549。 如果在当前解决方案中定义了服务,请尝试构建解决方案并再次添加服务引用。

知道怎么解决吗???

【问题讨论】:

    标签: c# wcf svcutil.exe wcf-wshttpbinding


    【解决方案1】:

    尝试以下方法:

    在 devenv.exe 所在的 Visual Studio 安装目录(例如 C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE)中,将此部分添加到 devenv.exe.cofig 中

    <system.serviceModel>
    <client>
      <endpoint binding="customBinding" bindingConfiguration="largeServiceBinding" contract="IMetadataExchange" name="http" />
    </client>
    
    <bindings>
      <customBinding>
        <!-- NOTE: The binding name must be the same as specified in the config file of the wcf service -->
        <binding name="largeServiceBinding" >
          <textMessageEncoding>
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
          </textMessageEncoding>
    
          <httpTransport transferMode="Buffered" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647"/>
        </binding>
    
      </customBinding>
    </bindings>
    </system.serviceModel>
    

    在 WCF 服务的 app.config 中添加相同的绑定:

    <bindings>
      <customBinding >
        <!-- NOTE: The binding name must be the same as specified in the devenv.exe.config file located ..\Common7\IDE folder of the VS installation directory -->
        <binding name="largeServiceBinding" >
          <textMessageEncoding>
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647"
              maxNameTableCharCount="2147483647" />
          </textMessageEncoding>
          <httpTransport transferMode="Buffered" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647"/>
        </binding>
      </customBinding>
    </bindings>
    

    请注意,两个文件中绑定标签的名称属性必须匹配(例如 largeServiceBinding)

    最后将以下 mex 端点添加到您的服务标签中:

     <endpoint address="mex" binding="customBinding" contract="IMetadataExchange" bindingName="testBinding" bindingConfiguration="largeServiceBinding" name="http"/>
    

    这可能看起来像这样:

     <services>
      <service behaviorConfiguration="MyServiceBehavior"
        name="MyService.MyService">
        <endpoint address="" binding="wsHttpBinding" contract="MyService.IMyService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="customBinding" contract="IMetadataExchange" bindingName="testBinding" bindingConfiguration="largeServiceBinding" name="http"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8731/Design_Time_Addresses/MyService/MyService/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    

    【讨论】:

    • 感谢您的回复,我们会尽力让您知道结果。
    • 成功了,谢谢。之后我必须在客户端更改服务端点设置。谢谢!!!!
    • 这也对我有用,但没有必要添加新的绑定,我只是用上面的内容更新了readerQuotas
    【解决方案2】:

    我知道已经有一段时间了,但我遇到了同样的问题并找到了其他(更简单的)解决方案in codeproject

    在给定的解决方案中,值是在代码中设置的,而不是在 .config 文件中设置的。

            BasicHttpBinding binding = new BasicHttpBinding();
            binding.Security.Mode = BasicHttpSecurityMode.Transport;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
            binding.MaxReceivedMessageSize = 50000000;
            binding.ReaderQuotas.MaxArrayLength = 50000000;
            binding.ReaderQuotas.MaxStringContentLength = 50000000;
            binding.ReaderQuotas.MaxNameTableCharCount = 50000000;
            EndpointAddress endpoint = new EndpointAddress(new Uri("https://server/EWS/Exchange.asmx"));
            ExchangeServicePortTypeClient ews = new ExchangeServicePortTypeClient(binding, endpoint);
    

    但是,我更改了 .config 文件中相关值(&lt;binding&gt;&lt;readerQuotas&gt; 部分中的值)并解决了问题(而不是添加自定义绑定):

                    <binding name="ITransactionProcessor" closeTimeout="00:01:00"
                        openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                        allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                        maxBufferSize="50000000" maxBufferPoolSize="524288" maxReceivedMessageSize="50000000"
                        messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                        useDefaultWebProxy="true">
                        <readerQuotas maxDepth="32" maxStringContentLength="50000000" maxArrayLength="50000000"
                            maxBytesPerRead="4096" maxNameTableCharCount="50000000" />
                        <security mode="TransportWithMessageCredential">
                            <transport clientCredentialType="None" proxyCredentialType="None" 
                                realm="" />
                            <message clientCredentialType="UserName" algorithmSuite="Default" />
                        </security>
                    </binding>
    

    我希望这会对某人有所帮助:)

    【讨论】:

      【解决方案3】:

      要认识到的一点是,该消息指的是 svcutil 阅读器配额而不是服务配额! Svcutil 对它可以读取多少元数据有限制。可以使用配置文件更改此限制。解决方案是为 svcutil 创建一个配置文件,并将其放在与该工具相同的文件夹中。下次运行 svcutil 时,将考虑配置文件值。

      http://geekswithblogs.net/claraoscura/archive/2007/08/20/114806.aspx

      【讨论】:

        【解决方案4】:

        在你的 app.config 或 dll.config 在客户端添加:

        <configuration>
        <system.serviceModel>
        <bindings>
        <netTcpBinding>
        <binding name="myMex" maxReceivedMessageSize="1024000"> <!-- modify this to avoid stupid error -->
        <readerQuotas maxNameTableCharCount="163840" /> <!-- DO NOT touch this one -->
        <security mode="None" />
        </binding>
        </netTcpBinding>
        </bindings>
        
        ...
        
        <client>
        <endpoint binding="netTcpBinding" bindingConfiguration="myMex"
        contract="IMetadataExchange" name="net.tcp" />
        
        ...
        
                </client>
            </system.serviceModel>
        </configuration>
        

        你去吧! 这是 WCF 真正令人讨厌的事情之一,而且谷歌经常会给你带来很多 bs。浪费了很多时间。

        【讨论】:

          猜你喜欢
          • 2011-01-30
          • 2013-08-16
          • 1970-01-01
          • 2012-12-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多