4

我有一个用代码创建的自托管 Web 服务:

protected void StartService(Type serviceType, Type implementedContract, string serviceDescription)
{
    Uri addressTcp = new Uri(_baseAddressTcp + serviceDescription);
    ServiceHost selfHost = new ServiceHost(serviceType, addressTcp);
    Globals.Tracer.GeneralTrace.TraceEvent(TraceEventType.Information, 0, "Starting service " + addressTcp.ToString());
    try
    {
        selfHost.AddServiceEndpoint(implementedContract, new NetTcpBinding(SecurityMode.None), "");

        ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
        selfHost.Description.Behaviors.Add(smb);
        System.ServiceModel.Channels.Binding binding = MetadataExchangeBindings.CreateMexTcpBinding();
        selfHost.AddServiceEndpoint(typeof(IMetadataExchange), binding, "mex");
        selfHost.Open();

        ServiceInfo si = new ServiceInfo(serviceType, implementedContract, selfHost, serviceDescription);
        try
        {
            lock (_hostedServices)
            {
                _hostedServices.Add(serviceType, si);
            }
        }
        catch (ArgumentException)
        {
             //...
        }
    }
    catch (CommunicationException ce)
    {
        //...
        selfHost.Abort();
    }
}

这工作正常,但是当我尝试发送大块数据时,我得到以下异常:

Error: The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter @@@ . The InnerException message was 'There was an error deserializing the object of type @@@. The maximum string content length quota (8192) has been exceeded while reading XML data. This quota may be increased by changing the MaxStringContentLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader.'. Please see InnerException for more details. at: at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)

The solution appears to be adding MaxStringContentLength property to the binding. I understand how to do it in the Web.config (link):

... binding name="wsHttpBindingSettings" maxReceivedMessageSize="2147483647">

I am looking for a way of modifying the binding's maxReceivedMessageSize in code. Is that even possible with the type of binding that I am using?

Thanks.

Edit: After learning some more (and with the guidance of the responses I received) I understand the problem: I was trying to modify the MEX part of the service, which is only used to advertise it, see link. I should have modified the binding of the NetTcpBinding (first line in the try statement). now my (working) code looks like this:

...
    try
    {
        //add the service itself

        NetTcpBinding servciceBinding = new NetTcpBinding(SecurityMode.None);
        servciceBinding.ReaderQuotas.MaxStringContentLength = 256 * 1024;
        servciceBinding.ReaderQuotas.MaxArrayLength = 256 * 1024;
        servciceBinding.ReaderQuotas.MaxBytesPerRead = 256 * 1024;
        selfHost.AddServiceEndpoint(implementedContract, servciceBinding, "");
...
4

3 回答 3

2

You need to look at the <ReaderQuotas> subelement under your binding - that's where the MaxStringContentLength setting lives....

  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="test">
          <readerQuotas maxStringContentLength="65535" />   <== here's that property!
        </binding>
      </netTcpBinding>
    </bindings>
  </system.serviceModel>

In code, you can set it like this:

NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
binding.ReaderQuotas.MaxStringContentLength = 65535;

and then use this binding for the service endpoint ...

selfHost.AddServiceEndpoint(implementedContract, binding, "");
于 2012-12-23T16:57:35.627 回答
1
var binding = new NetTcpBinding(SecurityMode.None);
binding.MaxReceivedMessageSize = 2147483647;//this your maxReceivedMessageSize="2147483647"
binding.ReaderQuotas.MaxStringContentLength = 2147483647;//this property need set by exception
selfHost.AddServiceEndpoint(implementedContract, binding , "");
于 2012-12-23T16:52:09.337 回答
0

My solution is an ASP.NET site hosting an Silverlight client, where the service client reference is in a Portable project. Services run over HTTPS with username authentication.

I ran into some problems when sending a picture (byte[]) over WCF, but resolved it as following:

My web site's web.config has an binding (under system.serviceModel) defined as such:

<bindings>
  <customBinding>
    <binding name="WcfServiceBinding" receiveTimeout="00:10:00" sendTimeout="00:10:00" closeTimeout="00:10:00" openTimeout="00:10:00">
      <security authenticationMode="UserNameOverTransport" />
      <binaryMessageEncoding></binaryMessageEncoding>
      <httpsTransport maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" keepAliveEnabled="true" />
    </binding>
  </customBinding>
</bindings>

In my portable lib I got a WCF service reference and define my binding in code as such:

public static CustomBinding ServiceBinding
{
    get
    {
        if (binding != null)
        {
            return binding;
        }

        binding = new CustomBinding
        {
            CloseTimeout = new TimeSpan(0, 2, 0),
            ReceiveTimeout = new TimeSpan(0, 3, 0),
            SendTimeout = new TimeSpan(0, 5, 0)
        };

        var ssbe = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
        binding.Elements.Add(ssbe);
        binding.Elements.Add(new BinaryMessageEncodingBindingElement());
        binding.Elements.Add(
            new HttpsTransportBindingElement { MaxReceivedMessageSize = 2147483647, MaxBufferSize = 2147483647 });

        return binding;
    }
}

To create my client I get the static binding definition:

private static DataServiceClient CreateClient()
{
    var proxy = new DataServiceClient(ServiceUtility.ServiceBinding, ServiceUtility.DataServiceAddress);
    proxy.ClientCredentials.SetCredentials();
    return proxy;
}

Works great for me. Good luck.

于 2014-06-08T13:16:40.487 回答