WCF DefaultBinding not used on new WsHttpBinding - wcf

I´m having a 3rd party library that connects to webservice at specific endpoints.
With some services, i get the following exception:
Message=The maximum nametable character count quota (16384) has been exceeded while reading XML data. The nametable is a data structure used to store strings encountered during XML processing - long XML documents with non-repeating element names, attribute names and attribute values may trigger this quota. This quota may be increased by changing the MaxNameTableCharCount property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 1339.
The solution is, to increase the ReaderQuoata.
WCF suggests this via config files.
My app.config now looks like:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
</startup>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding>
<readerQuotas maxNameTableCharCount="2147483647" />
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
When i now create a new WsHttpBinding, the value of it is still the default value of 16384.
class Program
{
static void Main(string[] args)
{
WSHttpBinding x = new WSHttpBinding();
Console.WriteLine(x.ReaderQuotas.MaxNameTableCharCount); //prints 16384
}
}
What am i missing?

WSHttpBinding x = new WSHttpBinding(); creates a new instance of WSHttpBinding with the framework default values. Even though you have a default binding configuration defined in the configuration file, it is not being used by your code (See WSHttpBinding.cs for the source code). In other words, calling the parameterless constructor of WSHttpBinding does not apply the default binding from any associated config files, at least that I could see.
You have a couple of options here. First, give a name for the binding configuration in your config file and reference that. Second, assign the values to the XmlDictionaryReaderQuotas when you create the binding programatically.
Option 1
<bindings>
<wsHttpBinding>
<binding name="MyBinding">
<readerQuotas maxNameTableCharCount="2147483647" />
</binding>
</wsHttpBinding>
</bindings>
WSHttpBinding x = new WSHttpBinding("MyBinding");
Option 2
WSHttpBinding x = new WSHttpBinding();
x.ReaderQuotas rq = new XmlDictionaryReaderQuotas();
rq.MaxNameTableCharCount = Int32.MaxValue;

Did you try this link https://social.msdn.microsoft.com/Forums/vstudio/en-US/17592561-c470-452a-a52c-2a5a2839582c/metadataexchangeclient-and-nametable-character-count-quota?forum=wcf
this is a bug in our code (the binding you pass is ignored for
HTTP-GET). There are a few workarounds
can you see if any of them will work for you?
Is the service a WCF service? If so, can you enable a mex endpoint on the service? The binding will be used work for the mex endpoint.
Can
you use the Discovery protocol(http://msdn2.microsoft.com/en-us/library/system.web.services.discovery.discoveryclientprotocol.aspx)
to get the metadata from your service? The XML readers used by this
class don’t have any quotas.

Related

How to consume WCF Service in Orchard

I am trying to consume a service in my module in the module web config I added my service config as the following.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="WSEventSoap" />
<binding name="BasicHttpBinding_ITwitterService" />
<binding name="BasicHttpBinding_ILoyalty">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint name="BasicHttpBinding_ITwitterService"
address="wwww.mysite.com/MediaServices/TwitterService.svc"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_ITwitterService"
contract="TwitterService.ITwitterService" />
</client>
</system.serviceModel>
within the modules web.config. What I am noticing is that
I can't seem to access web config settings in my module
I keep getting the following error.
Could not find default endpoint element that references contract 'TwitterService.ITwitterService' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.
Please help.
On the site I'm currently working on, like Betrand suggests, we've avoided modifying the global web.config to ensure the module is portable between projects.
Instead we've just created the Binding and Endpoint in code, rather that them getting pulled from the config. We've added our own setting to the Orchard site settings to let the user specify the endpoint address via the admin dashboard, which is the only part we actually need to be configurable.
To do this, in the module add a service reference as normal, if it adds those sections to your module web.config remove them as you won't be using them.
Then in code do something like
Binding binding = new BasicHttpBinding();
EndpointAddress address = new EndpointAddress("http://localhost:8050/MyService/");
using (var client = new MyServiceClient(binding, endpointAddress))
{
client.MyMethod();
}
There's plenty examples of this on Stackoverflow and elsewhere (e.g. WCF: How can I programatically recreate these App.config values?)

WCF programmatically set endpoint address: No elements matching the key were found in the configuration element collection

I'm performing what I believed was a pretty basic task. We have an environment with multiple servers (DEV, TEST, PRODUCTION) and I'd like to programmatically change the service endpoint. To do this I am creating a new EndPointAddress and instantiating the client as:
BasicHttpBinding binding = new BasicHttpBinding("BasicHttpBinding_IMyService");
EndpointAddress endpoint = new EndpointAddress(new Uri("http://domain.name/myservice.svc"));
MyService.MyServiceClient client = new MyService.MyServiceClient(binding, endpoint);
I am receiving the following error.
No elements matching the key 'BasicHttpBinding_IMyService' were found in the configuration element collection.
I have included my app.config below but, as you can see, I do have the binding defined.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService" >
<... removed directives for ease of reading ...>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://domain.name/MyService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyService"
contract="MyService.IMyService" name="BasicHttpBinding_IMyService" />
</client>
</system.serviceModel>
I'm sorry if this is a simple question but I haven't been able to identify the problem. I'll call it the 'late-Friday brain fog', and maybe you can call it 'easy points'?
Thanks!
The bindings in the Web.config of the WCF application and the app.config of the client application must match

WCF service hosted in IIS 7 - binding configuration settings are ignored

I have a WCF service operation that accepts a byte array as part of its data contract. The service is only exposed internally (not to the internet), and I want to increase the quotas to allow for a 10MB byte array.
The service is hosted in IIS7. When I try to send a byte array over the default length, I get the following exception message:
There was an error deserializing the object of type
MyService.ServiceContracts.Data. The maximum array length quota
(16384) has been exceeded while reading XML data. This quota may be
increased by changing the MaxArrayLength property on the
XmlDictionaryReaderQuotas object used when creating the XML reader.
Line 1, position 22991.
Here's the configuration:
<system.serviceModel>
<netTcpBinding>
<binding name="largeBinaryBinding" maxReceivedMessageSize="10001000"
maxBufferPoolSize="80008000" maxBufferSize="10001000"
receiveTimeout="00:01:00" openTimeout="00:01:00"
closeTimeout="00:01:00" sendTimeout="00:01:00">
<readerQuotas maxArrayLength="10000000" />
</binding>
</netTcpBinding>
<services>
<service name="MyService">
<endpoint binding="netTcpBinding"
bindingConfiguration="largeBinaryBinding"
bindingNamespace="http://my.services.co.uk/MyService"
contract="Services.MyService.ServiceContracts.IMyService" />
</service>
</services>
</system.serviceModel>
So my configuration allows for larger messages, but IIS seems to be ignoring this - how do I stop this and allow large messages through?
Again, just after I post a question I discover the answer!
When using WAS, you need to specify the full class name of the service in the configuration's service name. So in my example, I had my service implementation class called MyService, in the namespace Services. Therefore, in the configuration, I need
<service name="Services.MyService">
...
Otherwise IIS silently ignores your carefully crafted configuration! How convenient.

bindingConfiguration vs bindingName

What exactly is the difference between bindingConfiguration and bindingName elements in a WCF endpoint element? The reason that I ask is I am creating an endpoint which uses basicHttpBinding and SSL. I configured the web.config like this:
<basicHttpBinding>
<binding name="basicHttps">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
<endpoint binding="basicHttpBinding" bindingConfiguration="basicHttps" contract="Hsp.Services.Interface.Catalog.ICatalogService" address="" />
However, when using bindingConfiguration then https isn't working. When I change bindingConfiguration to bindingName it works as expected. So, what exactly is the difference between the two?
The binding= attribute just defines, which binding (protocol) you want - basicHttpBinding, wsHttpBinding, netTcpBinding etc.
Those bindings all have system default values - if you don't specify any binding configuration, those system defaults will be used.
What you've defined in your <bindings> section of your config is a binding configuration - a set of parameters for your binding of choice that will be used instead of the system defaults.
So the binding= and the bindingConfiguration= need to match - you cannot define one binding (e.g. basicHttpBinding) but then assign a binding configuration for a different binding.
That however still doesn't explain why your https doesn't work - that must be some other problem. Can you elaborate a bit more? How does it not work? Just no response, or do you get an error (if so: what is that error??)
From the MSDN documentation
bindingConfiguration: A string that specifies the binding name of the binding to use when the endpoint is instantiated. The binding name must be in scope at the point the endpoint is defined. The default is an empty string. This attribute is used in conjunction with binding to reference a specific binding configuration in the configuration file. Set this attribute if you are attempting to use a custom binding. Otherwise, an exception may be thrown.
bindingName: A string that specifies the unique qualified name of the binding for definition export through WSDL. The default is an empty string.
I've never used bindingName, but it seems to only affect the WSDL generated for your endpoint. If something isn't working when you use bindingConfiguration="basicHttps", then it sounds like you have a misconfiguration that's preventing it from working correctly (if no bindingConfiguration is specified, the defaults will be applied, which is what's happening when you change bindingConfiguration to bindingName). I don't think <transport clientCredentialType="None"/> is valid, the possible values are Basic, Certificate, Digest, Windows, or NTLM. See Transport Security Overview
Your service configuration binding is incorrect. So when you correctly refer to your binding configuration using the bindingConfiguration attribute, your service is not working. When you use the bindingName attribute, which is an invalid used attribute in your case, the service just starts a basicHttpBinding without looking at your custom configuration, which seems to work correctly.
For the different between the two elements look at: http://msdn.microsoft.com/en-us/library/ms731320.aspx.
So, using the bindingConfiguration attribute is the only correct thing. Now we still need to look at what is wrong with you binding configuration itself :-) See the following example to extract your relevant information from.
<system.web.extensions>
<scripting>
<webServices>
<authenticationService enabled="true"
requireSSL = "true"/>
</webServices>
</scripting>
</system.web.extensions>
<system.serviceModel>
<services>
<service name="System.Web.ApplicationServices.AuthenticationService"
behaviorConfiguration="AuthenticationServiceTypeBehaviors">
<endpoint contract=
"System.Web.ApplicationServices.AuthenticationService"
binding="basicHttpBinding"
bindingConfiguration="userHttps"
bindingNamespace="http://asp.net/ApplicationServices/v200"/>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="userHttps">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="AuthenticationServiceTypeBehaviors">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment
aspNetCompatibilityEnabled="true"/>
</system.serviceModel>
See http://msdn.microsoft.com/en-us/library/bb398990.aspx for more details.
bindingConfiguration
A string that specifies the binding name of the binding to use when the endpoint is instantiated. The binding name must be in scope at the point the endpoint is defined. The default is an empty string.
This attribute is used in conjunction with binding to reference a specific binding configuration in the configuration file. Set this attribute if you are attempting to use a custom binding. Otherwise, an exception may be thrown.
bindingName
A string that specifies the unique qualified name of the binding for definition export through WSDL. The default is an empty string.

Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it

When i'm using SessionMode = SessionMode.Required in servicecontract then i get this error
Contract requires Session, but Binding 'BasicHttpBinding' doesn't
support it or isn't configured properly to support it.
anyone tell me a solution?
This error message is seldom clear. Here the answer goes like this, basichttpbinding doesn't support session. So you have to use the below property if you want to use it.
[ServiceContract(SessionMode = SessionMode.Allowed)]
This means, If you are trying to configure multiple bindings like basichttp, wshttp, net.tcp, WCF will automatically enable session for other than basichttp binding. so if you put SessionMode.Required instead of Allowed, then you are forced not to use basichttpbinding.
That said, solving this issue usually would require something like this:
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="wsHttpBinding" bindingConfiguration="wsHttpBindingConfiguration" />
</protocolMapping>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBindingConfiguration" transactionFlow="true" />
</wsHttpBinding>
.......
As it's listed here, choose wsHttpBinding or NetTcpBinding.WSHttpBinding binding.