WCF Extensibility – Binding (and binding element) configuration extensions
This post is part of a series about WCF extensibility points. For a list of all previous posts and planned future ones, go to the index page .
After a heavy subject in the channels, this week’s post is about something simpler – configuration extensions for bindings and binding elements. Just like you can use extensions to define endpoint and service behaviors in configuration, both binding elements (to be used in custom bindings) and full binding settings can be defined using configuration as well, as long as we have the appropriate binding element and standard binding extensions in place. And despite my personal bias against configuration, the scenario I’ll show in this post is actually a perfect example where defining a binding in configuration can be a good choice.
Binding elements can be made “configurable” by using the BindingElementExtensionElement class (similar to the BehaviorExtensionElement class covered in a previous post). Bindings take a little more work, since we need two extension classes, one for the binding “section” (StandardBindingCollectionElement<TStandardBinding, TBindingConfiguration>) for the new binding type, and one for each specific binding “instance” (StandardBindingElement). The next sections will have more details about these classes.
Public implementations in WCF
Those are the public binding element extensions – those which can be used inside custom binding declarations in configuration. I’ll divide them in sections for the channel types which those binding elements create.
Encoders:
- BinaryMessageEncodingElement (<binaryMessageEncoding>): Adds a BinaryMessageEncodingBindingElement to the custom binding, defining that the communication will be encoded via the .NET Binary Format.
- ByteStreamMessageEncodingElement (<byteStreamMessageEncoding>, new in 4.0): Adds a ByteStreamMessageEncodingBindingElement to the custom binding, defining the message encoding as a stream of bytes. Useful for services which need access to the raw transport payload.
- MtomMessageEncodingElement (<mtomMessageEncoding>): Adds a MtomMessageEncodingBindingElement to the custom binding, defining the message encoding to be the Message Transmission Optimization Mechanism (MTOM).
- TextMessageEncodingElement (<textMessageEncoding>): Adds a TextMessageEncodingBindingElement to the custom binding, defining that the communication will be encoded via “normal” XML.
- WebMessageEncodingElement (webMessageEncoding, new in 3.5): Adds a WebMessageEncodingBindingElement to the custom binding. Since this is a “composite” encoder, the communication can be made via XML, JSON or the Raw mode.
Transports:
- PeerTransportElement (<peerTransport>): Adds a PeerTransportBindingElement to the custom binding. Used for peer-to-peer communication.
- NamedPipeTransportElement (<namedPipeTransport>): Adds a NamedPipeTransportBindingElement to the custom binding. Used for same-machine communication.
- TcpTransportElement (<tcpTransport>): Adds a TcpTransportBindingElement to the custom binding. Defines the communication to go over TCP according to the .NET Message Framing rules.
- HttpTransportElement (<httpTransport>): Adds a HttpTransportBindingElement to the custom binding. Defines that the communication will happen over unencrypted HTTP.
- HttpsTransportElement (<httpsTransport>): Adds a HttpsTransportBindingElement to the custom binding. Defines that the communication will happen over HTTPS (HTTP over SSL).
- MsmqIntegrationElement (<msmqIntegration>): Adds a MsmqIntegrationBindingElement to the custom binding. Defines that the communication will happen through MSMQ using one of the legacy protocols, such as COM, MSMQ native APIs or the System.Messaging APIs.
- MsmqTransportElement (<msmqTransport>): Adds a MsmqTransportBindingElement to the custom binding. Defines that the communication will happen through MSMQ using the native Message Queueing (MSMQ) protocol.
Protocol Channels:
- CompositeDuplexElement (<compositeDuplex>): Adds a CompositeDuplexBindingElement to the custom binding. Adds a callback channel to the binding to be used in duplex communication.
- OneWayElement (<oneWay>): Adds an OneWayBindingElement to the custom binding. Defines a channel which changes the shape of a request/reply inner channel to input / output (on client / server, respectively).
- PnrpPeerResolverElement (<pnrpPeerResolver>): Adds a PnrpPeerResolverBindingElement to the custom binding. Defines a channel which implements the Peer Name Resolution Protocol for peer-to-peer communication.
- PrivacyNoticeElement (<privacyNoticeAt>): Adds a PrivacyNoticeBindingElement to the custom binding. Defines the location of the privacy policy for a WS-Federation binding.
- ReliableSessionElement (<reliableSession>): Adds a ReliableSessionBindingElement to the custom binding. Adds a channel which changes the shape of a request/reply (or input/output) inner channel to request session / reply session (or input session / output session) by implementing the WS-RM protocol.
- SecurityElement (<security>): Adds a security binding element to the custom binding. The actual binding element type depends on the “mode” attribute of the <security> element.
- SslStreamSecurityElement (<sslStreamSecurity>): Adds a SslStreamSecurityBindingElement to the custom binding. Adds SSL support to an unencrypted channel (i.e., TCP).
- TransactionFlowElement (<transactionFlow>): Adds a TransactionFlowBindingElement to the custom binding. Defines the transaction flow support for the binding.
- UseManagedPresentationElement (<useManagedPresentation>): Adds a UseManagedPresentationBindingElement to the custom binding. It’s used mostly by CardSpace.
- WindowsStreamSecurityElement (<windowsStreamSecurity>): Adds a WindowsStreamSecurityBindingElement to the custom binding. Adds Windows security to the channel.
- DiscoveryClientElement (<discoveryClient>, new in 4.0): Adds a DiscoveryClientBindingElement to the custom binding. Used in client applications to allow them to access discoverable services without knowing their endpoint address in advance.
Those are public standard binding extensions.
- BasicHttpBindingElement (<basicHttpBinding>): Defines configurations for the BasicHttpBinding.
- MexHttpBindingElement (<mexHttpBinding>): Defines configurations for a binding for the WS-MessageExchange (MEX) protocol over HTTP.
- MexHttpsBindingElement (<mexHttpsBinding>): Defines configurations for a binding for the WS-MessageExchange (MEX) protocol over HTTPS.
- MexNamedPipeBindingElement (<mexNamedPipeBinding>): Defines configurations for a binding for the WS-MessageExchange (MEX) protocol over named pipes.
- MexTcpBindingElement (" href="https://msdn.microsoft.com/en-us/library/aa967279.aspx">" href="https://msdn.microsoft.com/en-us/library/aa967279.aspx"><mexTcpBinding> ): Defines configurations for a binding for the WS-MessageExchange (MEX) protocol over TCP.
- MsmqIntegrationBindingElement (<msmqIntegrationBinding>): Define configurations for the MsmqIntegrationBinding.
- NetMsmqBindingElement (<netMsmqBinding>): Define configurations for the NetMsmqBinding.
- NetNamedPipeBindingElement (" href="https://msdn.microsoft.com/en-us/library/ms731291.aspx">" href="https://msdn.microsoft.com/en-us/library/ms731291.aspx"><netNamedPipeBinding>): Define configurations for the NetNamedPipeBinding.
- NetPeerTcpBindingElement (<netPeerTcpBinding>): Define configurations for the NetPeerTcpBinding.
- NetTcpBindingElement (<netTcpBinding>): Define configurations for the NetTcpBinding.
- WebHttpBindingElement (" href="https://msdn.microsoft.com/en-us/library/bb412176.aspx">" href="https://msdn.microsoft.com/en-us/library/bb412176.aspx"><webHttpBinding>, new in 3.5):Define configurations for the WebHttpBinding.
- WS2007FederationHttpBindingElement (<ws2007FederationHttpBinding>, new in 3.0SP1): Define configurations for the WS2007FederationHttpBinding.
- WS2007HttpBindingElement (<ws2007HttpBinding>, new in 3.0SP1): Define configurations for the WS2007HttpBinding.
- WSDualHttpBindingElement (<wsDualHttpBinding>): Define configurations for the WSDualHttpBinding.
- WSFederationHttpBindingElement (<wsFederationHttpBinding>): Define configurations for the WSFederationHttpBinding.
- WSHttpBindingElement (<wsHttpBinding>): Define configurations for the WSHttpBinding.
- CustomBindingElement (<customBinding>): Define configurations for a CustomBinding, where the binding elements are explicitly defined.
The collection classes for those bindings above are located in the same namespace (and assembly) as their respective binding classes.
Class declaration
- public abstract class BindingElementExtensionElement : ServiceModelExtensionElement
- {
- public abstract Type BindingElementType
- {
- get;
- }
- protected internal abstract BindingElement CreateBindingElement();
- }
- public abstract partial class StandardBindingElement : ConfigurationElement
- {
- protected abstract Type BindingElementType
- {
- get;
- }
- protected abstract void OnApplyConfiguration(Binding binding);
- }
- public partial class StandardBindingCollectionElement<TStandardBinding, TBindingConfiguration> : BindingCollectionElement
- where TStandardBinding : Binding
- where TBindingConfiguration : StandardBindingElement, new()
- {
- }
To implement a binding element configuration extension, one needs to derive from BindingElementExtensionElement. The derived class needs to override the BindingElementType property to return the type of the binding element which that extension can create, and also the CreateBindingElement method, to actually return an instance of the binding element it configures. Notice that BindingElementExtensionElement is derived from System.Configuration.ConfigurationElement, so the class can (and should) use the ConfigurationPropertyAttribute to define attributes and sub-elements which need to be passed to the binding element at creation time.
To implement a new “standard binding” type, one needs first to derive from StandardBindingElement, and again override two members: the BindingElementType property (which should be called “BindingType”, since this doesn’t deal with binding elements, but I digress) to return the type of binding which will be created, and OnApplyConfiguration, which will be called with an uninitialized instance of the binding type to be set. This class is also derived from System.Configuration.ConfigurationElement, but unlike on the binding element extensions, I always have to override the Properties property as well to include the custom properties for that binding (it’s not automatically picked up by the runtime). Also notice that since a “blank” instance of the binding element is passed to the extension (instead of the extension creating one), the standard binding class needs to have a parameter-less constructor, otherwise it cannot be defined in configuration. Finally, we need to define a “collection element” for the new standard binding, deriving a class from StandardBindingCollectionElement<TStandardBinding, TBindingConfiguration>. This step is actually quite simple, as the base class (with generic parameters) does most of the legwork, and all one needs to do is to define the parameters as the new standard binding type and the standard binding configuration element type which will be used. The code example will show this in practice.
How to add binding element and binding extensions
Binding element: custom binding element extensions are added to the <system.serviceModel / extensions / bindingElementExtensions> element, and given an alias which can be used inside custom binding declarations:
- <system.serviceModel>
- <extensions>
- <bindingElementExtensions>
- <add name="myNewBindingElement"
- type="MyNamespace.MyBindingElementExtension, MyAssemblyName"/>
- </bindingElementExtensions>
- </extensions>
- </system.serviceModel>
Standard bindings: standard binding extensions are added to the <system.serviceModel / extensions / bindingExtensions> element, and given an alias which can be used as a child element of the <bindings> node. The type must be the assembly-qualified name of the class derived from StandardBindingCollectionElement, not the one derived from StandardBindingElement.
- <system.serviceModel>
- <extensions>
- <bindingExtensions>
- <add name="myNewBinding"
- type="MyNamespace.MyBindingElementCollection, MyAssemblyName"/>
- </bindingExtensions>
- </extensions>
- </system.serviceModel>
One note about extensions and Visual Studio: just like it happened with behavior extensions, VS will usually issue a warning about a schema violation when we use binding or binding element configuration extensions, and tag the extension with a squiggly line (see below). The warning states that it is not a valid child for the <binding> or <customBinding> elements. This is just a nuisance, as this error can be safely ignored and won’t cause any problems during runtime. But if you’re someone who gets bugged by warnings (or has a setting in the project to treat all warnings as errors, you can update the configuration schema in Visual Studio at \Program Files\Microsoft Visual Studio 10.0\Xml\Schemas\DotNetSchema.xsd (replace Program Files with Program Files (x86) for 64-bit OS, and replace 10.0 with the appropriate VS version) and update the schema to allow for this new element as well.
Real world example: configuration extensions for the “chaos monkey channel”
The “chaos monkey channel”, introduced in the post about channels, is great during testing of the system for resiliency over failures on dependent services. But as a system matures (or as it goes from the test to the production stage), one may want to tweak the amount of failures which the channel injects into the system. With a code-based binding element (as it was in the first sample), one would need to change the source code, then recompile it for every change in the “chaos controller”. Or one would simply add some external variable (i.e., registry, file, database, etc.) which would be read by the runtime when creating the channel. WCF configuration is nothing more than another external source, it just happens to be fairly well used (the .NET configuration system has been in use since the beginning of .NET), so it’s a good place for it to be. This is one of the (few, IMO) places which configuration actually makes sense.
And before I go further, the usual disclaimer: this is a sample for illustrating the topic of this post, this is not production-ready code. I tested it for a few scenarios and it worked, but I cannot guarantee that it will work for all scenarios. It also does not have a lot of error handling / good exception messages which a production-level code should have, as I’ve kept it simple for illustration purposes.
The project starts with the “Chaos Monkey Channel”. I won’t go into the details of that project, only on the configuration extensions this time. Just one small modification: the sample chaos controller was “promoted” from a nested class to a top-level one, and it got two parameters which can be passed to its constructor (to illustrate parameters in the configuration extensions).
- public class MyMonkeyController : IChaosController
- {
- Random rndGen;
- int percentFailure;
- public MyMonkeyController() : this(Environment.TickCount)
- {
- }
- public MyMonkeyController(int randomSeed) : this(randomSeed, 20)
- {
- }
- public MyMonkeyController(int randomSeed, int percentFailure)
- {
- this.rndGen = new Random(randomSeed);
- this.percentFailure = percentFailure;
- }
- public bool ShouldFault(ref Message request, out Message fault)
- {
- int rnd = this.rndGen.Next(0, 100);
- if (rnd < this.percentFailure)
- {
- var exception = new FaultException("Chaos!!!", new FaultCode("chaos!"));
- var messageFault = exception.CreateMessageFault();
- fault = Message.CreateMessage(request.Version, messageFault, "Chaos");
- return true;
- }
- else
- {
- fault = null;
- return false;
- }
- }
- }
Now we can start with the extension for the binding element. The class is actually quite simple, with a pair of properties to control both the random seed and the level of failure introduced by the channel. Those properties are picked up automatically by the configuration subsystem, so they can simply be used in the CreateBindingElement method.
- public class ChaosMonkeyElementExtension : BindingElementExtensionElement
- {
- private const string RandomSeedPropertyName = "randomSeed";
- private const string PercentFailurePropertyName = "percentFailure";
- public override Type BindingElementType
- {
- get { return typeof(ChaosMonkeyBindingElement); }
- }
- [ConfigurationProperty(RandomSeedPropertyName, IsRequired = false, DefaultValue = -1)]
- public int RandomSeed
- {
- get { return (int)base[RandomSeedPropertyName]; }
- set { base[RandomSeedPropertyName] = value; }
- }
- [ConfigurationProperty(PercentFailurePropertyName, IsRequired = false, DefaultValue = 20)]
- public int PercentFailure
- {
- get { return (int)base[PercentFailurePropertyName]; }
- set { base[PercentFailurePropertyName] = value; }
- }
- protected override BindingElement CreateBindingElement()
- {
- int randomSeed = this.RandomSeed;
- if (randomSeed < 0)
- {
- randomSeed = Environment.TickCount;
- }
- IChaosController controller = new MyMonkeyController(this.RandomSeed, this.PercentFailure);
- return new ChaosMonkeyBindingElement(controller);
- }
- }
And with it we can register this new extension class in the <system.serviceModel / extensions / bindingElementExtensions> list, as shown below.
- <system.serviceModel>
- <extensions>
- <bindingElementExtensions>
- <add name="chaosMonkey"
- type="ChaosMonkeyChannel.ChaosMonkeyElementExtension, ChaosMonkeyChannel"/>
- </bindingElementExtensions>
- </extensions>
- <bindings>
- <customBinding>
- <binding name="BindingWithChaos">
- <chaosMonkey percentFailure="50" />
- <binaryMessageEncoding />
- <httpTransport />
- </binding>
- </customBinding>
- </bindings>
- </system.serviceModel>
And we can now create a new custom binding in code which uses the new binding element (<chaosMonkey>), and use it in a program.
- var binding = new CustomBinding("BindingWithChaos");
- var factory = new ChannelFactory<ITest>(binding, new EndpointAddress(baseAddress + "/custom"));
- var proxy = factory.CreateChannel();
- for (int i = 0; i < 30; i++)
- {
- try
- {
- Console.WriteLine("10 + {0} = {1}", i, proxy.Add(10, i));
- }
- catch (FaultException ex)
- {
- Console.WriteLine("{0}: {1}", ex.GetType().Name, ex.Message);
- }
- }
And that’s it – the ChaosMonkeyBindingElement can now be defined in configuration. For the standard binding, if we’re using a certain binding element combination in a custom binding ofrten enough, sometimes we create a new Binding class so that we don’t have to always define the same custom binding over and over. In this example, I’ll create a new binding which has a chaos monkey element, plus a binary encoding, plus the HTTP transport.
- public class BinaryOverHttpWithChaosBinding : Binding
- {
- IChaosController controller;
- public BinaryOverHttpWithChaosBinding()
- : this(null)
- {
- }
- public BinaryOverHttpWithChaosBinding(IChaosController controller)
- {
- this.controller = controller;
- }
- public IChaosController Controller
- {
- get { return this.controller; }
- set { this.controller = value; }
- }
- public override BindingElementCollection CreateBindingElements()
- {
- if (this.controller == null)
- {
- throw new InvalidOperationException("The controller cannot be null.");
- }
- return new BindingElementCollection(new BindingElement[] {
- new ChaosMonkeyBindingElement(this.controller),
- new BinaryMessageEncodingBindingElement(),
- new HttpTransportBindingElement(),
- });
- }
- public override string Scheme
- {
- get { return new HttpTransportBindingElement().Scheme; }
- }
- }
This new binding can be used in code, but since this is a configuration post, let’s make it configurable as well. First off, the StandardBindingElement subclass for it. As I mentioned before, if I don’t override the “Properties” property, this does not work (unlike in the binding element extension, where it just worked).
- public class BinaryOverHttpWithChaosBindingElement : StandardBindingElement
- {
- private const string RandomSeedPropertyName = "randomSeed";
- private const string PercentFailurePropertyName = "percentFailure";
- [ConfigurationProperty(RandomSeedPropertyName, IsRequired = false, DefaultValue = -1)]
- public int RandomSeed
- {
- get { return (int)base[RandomSeedPropertyName]; }
- set { base[RandomSeedPropertyName] = value; }
- }
- [ConfigurationProperty(PercentFailurePropertyName, IsRequired = false, DefaultValue = 20)]
- public int PercentFailure
- {
- get { return (int)base[PercentFailurePropertyName]; }
- set { base[PercentFailurePropertyName] = value; }
- }
- protected override Type BindingElementType
- {
- get { return typeof(BinaryOverHttpWithChaosBinding); }
- }
- protected override void OnApplyConfiguration(Binding binding)
- {
- BinaryOverHttpWithChaosBinding chaosBinding = (BinaryOverHttpWithChaosBinding)binding;
- int randomSeed = this.RandomSeed;
- if (randomSeed < 0)
- {
- randomSeed = Environment.TickCount;
- }
- IChaosController controller = new MyMonkeyController(this.RandomSeed, this.PercentFailure);
- chaosBinding.Controller = controller;
- }
- protected override ConfigurationPropertyCollection Properties
- {
- get
- {
- var result = base.Properties;
- result.Add(new ConfigurationProperty("percentFailure", typeof(int), 20));
- result.Add(new ConfigurationProperty("randomSeed", typeof(int), -1));
- return result;
- }
- }
- }
Finally the standard binding collection element. This is essentially a one-liner, as the base class does all the work:
- public class BinaryOverHttpWithChaosBindingElementCollection
- : StandardBindingCollectionElement<BinaryOverHttpWithChaosBinding,
- BinaryOverHttpWithChaosBindingElement>
- {
- }
Now we can register that extension in the <system.serviceModel / extensions / bindingExtensions> list:
- <system.serviceModel>
- <extensions>
- <bindingExtensions>
- <add name="binaryHttpChaos"
- type="ChaosMonkeyChannel.BinaryOverHttpWithChaosBindingElementCollection, ChaosMonkeyChannel"/>
- </bindingExtensions>
- </extensions>
- <bindings>
- <binaryHttpChaos>
- <binding name="MyBinding" percentFailure="30" randomSeed="1" />
- </binaryHttpChaos>
- </bindings>
- <client>
- <endpoint name="allConfig"
- address="https://localhost:8000/Service/custom"
- binding="binaryHttpChaos"
- bindingConfiguration="MyBinding"
- contract="ChaosMonkeyChannel.ITest" />
- </client>
- </system.serviceModel>
And finally, we can use it in our test program:
- var binding = new CustomBinding("BindingWithChaos");
- var factory = new ChannelFactory<ITest>("allConfig");
- var proxy = factory.CreateChannel();
- for (int i = 0; i < 30; i++)
- {
- try
- {
- Console.WriteLine("10 + {0} = {1}", i, proxy.Add(10, i));
- }
- catch (FaultException ex)
- {
- Console.WriteLine("{0}: {1}", ex.GetType().Name, ex.Message);
- }
- }
And that’s it for configuration extensions.
[Code in this post]
Comments
- Anonymous
December 22, 2011
Hi Carlos,Great series of posts on WCF extensibility, thank you! I was wondering what we need to do if the binding element needs to return a json message back to the client. In an error case, I'm trying to return a message by using Message.CreateMessage and passing a custom BodyWriter, that is supposed to format my custom error object using DataContractJsonSerializer. I also set the HttpResponseMessageProperty on the message, set status code, and set content type of response header to "application/json". When I see my traffic in Fiddler, the response content type header is json, and the status code is whatever I set it to. however, the actual message body is still in XML and not Json. I'm using a webHttpEndPoint and can see that the WebMessageEncodingBindingElement is present.would appreciate any pointers.thanks,Priya - Anonymous
December 22, 2011
I figured this out, and have posted the solution in the WCF forum here :social.msdn.microsoft.com/.../08e7edab-3edf-4fb3-af85-34edd1f62bf5. Basically, I need to set a WebBodyFormatMessageProperty property. - Anonymous
December 22, 2011
Hi Priya, thanks for the comments. Yes, the WebMessageEncodingBindingElement holds a "composite" encoder which needs some additional information to know how it will encode the outgoing message, and that information is given by the WebBodyFormatMessageProperty as you mentioned. Glad you figured it out! - Anonymous
February 07, 2014
Hi Carlos, How I can set maxReceivedMessageSize attribute for the below binding extension?<binaryHttpChaos> <binding name="MyBinding" percentFailure="30" randomSeed="1" /> </binaryHttpChaos> - Anonymous
February 07, 2014
Biju, you can define a new [ConfigurationProperty] for that value you want passed in. Then, when creating the binding element collection, use that value to set the MaxReceivedMessageSize on the HttpTransportBindingElement. - Anonymous
February 10, 2014
Carlos Thanks for your quick response. Please find below the binding extension I created internal class InternalBindingCollectionElement : StandardBindingCollectionElement<UnSecuredWSHTTPBinding, InternalBindingElement> { } class InternalBindingElement : StandardBindingElement { protected override void OnApplyConfiguration(Binding binding) { } protected override Type BindingElementType { get { return typeof(UnSecuredWSHTTPBinding); } } } public class UnSecuredWSHTTPBinding : CustomBinding { private static WSHttpBinding CreateSecuredWSHTTPBinding() { WSHttpBinding wsBinding = new WSHttpBinding(); wsBinding.Security.Mode = SecurityMode.Transport; wsBinding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic256; wsBinding.Security.Message.NegotiateServiceCredential = false; return wsBinding; } private static CustomBinding CreateUnSecuredWSHTTPBinding() { WSHttpBinding wsBinding = CreateSecuredWSHTTPBinding(); CustomBinding unsecuredWSHTTPBinding = new CustomBinding(wsBinding.CreateBindingElements()); var httpTransportBindingElement = new UnSecuredTransportBindingElement(); httpTransportBindingElement.MaxReceivedMessageSize = MaxContentLengthLimit; HttpsTransportBindingElement httpsTransportBindingElement = unsecuredWSHTTPBinding.Elements.Find<HttpsTransportBindingElement>(); int httpsTransportElementIndex = unsecuredWSHTTPBinding.Elements.IndexOf(httpsTransportBindingElement); unsecuredWSHTTPBinding.Elements[httpsTransportElementIndex] = httpTransportBindingElement; // Return modified binding. return unsecuredWSHTTPBinding; } public override BindingElementCollection CreateBindingElements() { return CreateUnSecuredWSHTTPBinding().Elements; } public override string Scheme { get { return "http"; } } private static int MaxContentLengthLimit { get { return Int32.MaxValue; } } } - Anonymous
February 10, 2014
class UnSecuredTransportBindingElement : HttpTransportBindingElement, ITransportTokenAssertionProvider { public class Caps : ISecurityCapabilities { public ProtectionLevel SupportedRequestProtectionLevel { get { return ProtectionLevel.EncryptAndSign; } } public ProtectionLevel SupportedResponseProtectionLevel { get { return ProtectionLevel.EncryptAndSign; } } public bool SupportsClientAuthentication { get { return false; } } public bool SupportsClientWindowsIdentity { get { return false; } } public bool SupportsServerAuthentication { get { return true; } } } public override T GetProperty<T>(BindingContext context) { if (typeof(T) == typeof(ISecurityCapabilities)) return new Caps() as T; return base.GetProperty<T>(context); } public System.Xml.XmlElement GetTransportTokenAssertion() { return null; } }I configured my WCF service to use this binding extension and while accessing the WCF from Clients, I got the following errorSystem.ServiceModel.CommunicationException: The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. ---> System.ServiceModel.QuotaExceededException: The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.In the above bindingextension class, I set this value as Int32.MaxValue (ie, 2,147,483,647). But somehow in Services is taking the default value (65536). Any idea why this value got overridden? - Anonymous
February 11, 2014
Hi Carlos,It was my mistake. I forgot to change it in the client config file.Thanks - Anonymous
February 11, 2014
Great, glad to see your issue has been solved.