简体   繁体   中英

Configuring a WCF service binding in code

I have a self hosted web service that is created in code:

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();
    }
}

This works ok, but when I try to send large chunks of data I get the following exception:

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, "");
...
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 , "");

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, "");

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM