无法为代码中生成的BasicHttpBinding设置ReaderQuotas

时间:2011-07-12 21:18:41

标签: vb.net wcf wcf-binding

我有一个项目,要求生成一个没有依赖项的可执行文件,这将根据传递给它的命令行参数自动将数据提交到WCF服务。因此,我无法在App.config文件中配置WCF绑定和配额,因此我在代码中生成BasicHttpBinding以在标注WCF客户端对象时使用。

但是,WCF服务接受相对较小的Excel电子表格的二进制数据,最终约为30kb,因此绑定ReaderQuotas的默认配置设置不足。但是,我尝试将代码增加到1MB时,每次调用服务时都会失败。

我试图用以下两种方式设置绑定,首先是在构造函数本身中:

Private theBinding As New BasicHttpBinding With {
    .SendTimeout = TimeSpan.FromMinutes(1),
    .OpenTimeout = TimeSpan.FromMinutes(1),
    .CloseTimeout = TimeSpan.FromMinutes(1),
    .ReceiveTimeout = TimeSpan.FromMinutes(10),
    .AllowCookies = False,
    .BypassProxyOnLocal = False,
    .HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
    .MessageEncoding = WSMessageEncoding.Text,
    .TransferMode = TransferMode.Buffered,
    .UseDefaultWebProxy = True,
    .MaxBufferSize = 1048576,
    .MaxReceivedMessageSize = 1048576,
    .ReaderQuotas = New XmlDictionaryReaderQuotas With {
        .MaxDepth = 32,
        .MaxStringContentLength = 8192,
        .MaxArrayLength = 1048576,
        .MaxBytesPerRead = 4096,
        .MaxNameTableCharCount = 16384
    }
}

还可以删除上述代码中的ReaderQuotas setter,并在表单加载时使用System.Reflection将其设置为最大值。我意识到这个方法更适用于在配置文件中创建的绑定,因此通常是不可变的,但我认为尝试它不会有什么坏处。

theBinding.GetType.GetProperty("ReaderQuotas").SetValue(theBinding, XmlDictionaryReaderQuotas.Max, Nothing)

使用WCF客户端构造函数的最终重载标注WCF客户端:

Using theClient As New WCFServiceClient(theBinding, theEndpoint)
    ...
End Using

但是,在调用WCF客户端时仍然会收到以下异常:

  

System.ServiceModel.ProtocolException :格式化程序在尝试反序列化消息时抛出异常:出现错误   在尝试反序列化参数http://tempuri.org/:theObject时。   InnerException消息是'反序列化时出错   RootNameSpace.ObjectType类型的对象。最大数组长度   读取XML数据时已超出quota(16384)。这个配额可能   通过更改上的MaxArrayLength属性来增加   创建XML阅读器时使用的XmlDictionaryReaderQuotas对象。   第1行,第46272行。'。有关详细信息,请参阅InnerException。

负责人是会议桌。在正确配置读者配额方面,我真的可以使用一些指导来解决这个问题。

2 个答案:

答案 0 :(得分:1)

检查服务的配置文件(如果有)或其使用的绑定设置。客户端可能正好发送消息,但服务拒绝它,因为它仍然使用默认值。

答案 1 :(得分:0)

正如Tim所建议的,此问题的解决方案是正确配置IIS服务端点以读取大型邮件,而不仅仅是客户端。由于我没有发现关于这样做的现成/准确/全面的信息,我在这里为那些关注的人重现我的解决方案。

首先,使用适当的阅读器配额设置配置基本HTTP绑定,如下所示:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="basicHttpBinding_IMyService" maxReceivedMessageSize="2147483647">
                <readerQuotas maxDepth="32" maxArrayLength="2147483647" maxStringContentLength="2147483647"
                              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
            </binding>
        </basicHttpBinding>
    </bindings>
<system.serviceModel>

要考虑的重要字段是maxArrayLength的{​​{1}}和maxStringcontentLength属性以及readerQuotas的{​​{1}}属性的值。我已将它们设置为最大值 - 我相信 - 在此示例中,但在我的实际实现中,我选择了1MB(1048576)的值。根据您的服务情况设置最适合您的价值观。然后使用刚刚生成的绑定配置为合同指定端点:

maxReceivedMessageSize

请注意,在我的情况下,没有必要设置端点的地址。值得一提的是,我的目标是.NET 4.0 Framework,并在binding的托管环境中启用了多个站点绑定。您的里程可能会有所不同。