RELATED: " Choosing the Right Web Service Binding " and " MVC Model Binding "

In "Custom Bindings: Part I" I explained how to create a custom binding element, and how to programmatically and declaratively configure that element for an endpoint. Creating custom binding elements is one way to inject custom functionality into the channel stack, such as customizing the transport, the message encoder, or adding new features. A CustomBinding instance is used to select binding elements to configure the channel stack, but you can simplify reusable configurations by creating a custom binding type that encapsulates the desired features exposed by pre-existing or custom binding elements.

In this article, I ll explain how to create a custom binding type, along with other types necessary to support declarative configuration.

 

Customizing Binding Configurations

You have several options when you configure service endpoints and one of the standard bindings does not expose access to the desired channel functionality, including:

  • Use a CustomBinding to build the channel stack by hand and reach into features exposed by individual binding elements.
  • Create a custom BindingElement to add your own custom functionality to the CustomBinding configuration.
  • Extend one of the standard bindings to inject custom functionality or to encapsulate default settings.
  • Create a custom binding to encapsulate building a collection of pre-existing or custom binding elements for the channel stack.

All these approaches can be configured programmatically or declaratively. Of course, you must write additional code to support declarative configuration for custom types, such as custom binding elements (as I discussed in my last article) and custom bindings (to be discussed in this article).

In the following sections I ll first describe how to create a custom binding type, then show you how to create a custom binding element to configure the binding declaratively.

 

Creating a Custom Binding

Once you ve determined that you want to encapsulate a set of channel features into a custom binding, you must decide if you want to extend an existing standard binding and alter its initialization, or if you want to create a completely new binding type.

By extending an existing standard binding you inherit all its properties, but you can do interesting things, such as:

  • Encapsulate the initialization of your preferred default settings for the standard binding.
  • Extend or alter the binding to introduce new channel features with your own custom binding elements.
  • Expose additional properties to be used to configure those default settings and new channel features.

When you create a custom binding type, you have complete control over the properties you want to expose, as well as choice of binding elements that will be used to build the channel stack. In fact, when you create a custom binding type, you ll typically do the following:

  • Create a class that inherits the abstract binding type.
  • Define properties representative of information you need to collect to build the channel stack.
  • Supply useful constructors to initialize the binding and its key properties.
  • Provide an implementation for the abstract method, CreateBindingElements, where you ll construct the binding elements that compose the channel stack.
  • Provide an implementation for the abstract read-only property, Scheme, where you ll return the scheme supported by the binding.

Let s take a look at these steps in the context of a specific example.

 

Custom Binding Example: AssertEncryptionHttpBinding

Last month I explained how to create a custom transport binding element that would allow you to configure WCF to receive UserName credentials without encryption. The binding element, AssertEncryptionHttpTransportBindingElement, extended the HttpTransportBindingElement and injected a custom ISecurityCapabilities that asserts support for encryption to fake a secure channel. The purpose of this is to support scenarios where an SSL processing load balancer intercepts messages and handles decryption prior to forwarding messages to the appropriate WCF service. This is necessary only in this scenario because, by default, WCF disallows sending credentials without encryption.

Figure 1 illustrates the requirements of this scenario. Essentially, a WCF client may send credentials by transport or message over an SSL connection, but the target WCF service must receive those credentials without encryption because the load balancer will process the SSL encryption and forward the message unencrypted.


Figure 1: Security semantics for the SSL load balancer scenario.

Instead of creating a CustomBinding that uses this custom transport binding element, this time I ll create a custom binding type that encapsulates adding the appropriate transport binding element, along with setting up other required binding elements. Because the security features of this binding are limited to a few scenarios, I will not extend BasicHttpBinding or WSHttpBinding. Instead, I ll create a new type, AssertEncryptionHttpBinding, that directly extends the binding type. Listing One shows the complete listing for this new binding.

 

Selecting Properties for AssertEncryptionHttpBinding

Let s start by discussing the new properties exposed by this binding. The choice of properties I exposed is directly linked to the information I wanted to gather to properly initialize each binding element to compose the channel stack. The binding base type provides an implementation for the common timeout settings (OpenTimeout, CloseTimeout, SendTimeout, and ReceiveTimeout); thus, the custom binding inherits these properties. Beyond these, I chose to expose the properties described in Figure 2 some of which are common to most bindings, others not.

 

Binding Property

Usage

MessageEncoding

Sets the type of message encoder based on the WSMessageEncoding enumeration with the options Text or Mtom.

MessageVersion

Sets the format for SOAP messaging and WS-Addressing based on the MessageVersion type with options: Soap11, Soap11WSAddressing10, Soap11WSAddressingAugust2004, Soap12, Soap12WSAddressing10, or Soap12WSAddressingAugust2004.

MaxReceivedMessageSize

Sets the size quota for received messages.

ReaderQuotas

Sets the size quota for strings, arrays, and other reader quotas.

SecurityMode

Sets the chosen security features for the binding based on a custom enumeration, AssertEncryptionHttpSecurityMode, with options: None, UserNameOverTransport, or UserNameOverMessage.

Figure 2: New properties exposed by AssertEncryptionHttpBinding.

These property settings are used to initialize the transport, encoder, and security features of the binding.

I exposed the MessageEncoding property to be consistent with other HTTP bindings that support Text and Mtom encoding, using the WSMessageEncoding enumeration type. This value is used to choose between TextMessageEncodingBindingElement and MtomMessageEncodingBindingElement when CreateBindingElements is called to produce the binding element collection for the channel stack.

Quota-related properties including MaxReceivedMessageSize and the ReaderQuotas collection allow for customizing these settings, as this is frequently necessary to support passing large files, arrays, or strings. The value for MaxReceivedMessageSize is used to initialize the equivalent property on the transport binding element, which, in this case, is an instance of the custom binding element described last time (AssertEncryptionHttpTransportBindingElement). The value for ReaderQuotas is used to initialize the same on the two message encoder instances, so that both are correctly initialized prior to building the binding element collection.

By exposing a MessageVersion property, the binding can be initialized using the BasicHttpBinding or WSHttpBinding equivalent, or some other value that is required for interoperability. This property is based on the MessageVersion type and, like ReaderQuotas, its value is used to initialize the two message encoder instances. One interesting thing to point out is that the new keyword is used to hide the binding base type s implementation of MessageVersion, which is read-only. This has no impact on the polymorphic behavior of this property because the base implementation relies on the binding element collection to return the correct value from the selected message encoder.

The SecurityMode property for this custom binding implementation is based on a custom enumeration type, AssertEncryptionHttpSecurityMode, as shown here:

public enum AssertEncryptionHttpSecurityMode

{

   None,

   UserNameOverTransport,

   UserNameOverMessage

}

This binding supports three scenarios for passing credentials: no credentials, basic username, and password credentials passed in HTTP headers and username and password passed in the message.

The table in Figure 3 summarizes a typical set of SecurityMode and MessageVersion combinations for the AssertEncryptionHttpBinding and how those settings would relate to the standing binding equivalent the client application would use to send messages. This is important, because it governs how the CreateBindingElements override will choose and configure binding elements.

SecurityMode

MessageVersion

Standard Binding Equivalent

None

Soap11

BasicHttpBinding + BasicHttpSecurityMode.Transport + HttpClientCredentialType.None

None

Soap12WSAddressing10

WSHttpBinding + disable secure sessions and negotiation + SecurityMode.Transport + HttpClientCredentialType.None

UserNameOverTransport

Soap11

BasicHttpBinding + BasicHttpSecurityMode.Transport + HttpClientCredentialType.Basic

UserNameOverTransport

Soap12WSAddressing10

WSHttpBinding + disable secure sessions and negotiation + SecurityMode.Transport + HttpClientCredentialType.Basic

UserNameOverMessage

Soap11

BasicHttpBinding + BasicHttpSecurityMode.TransportWithMessageCredential + BasicHttpMessageCredentialType.UserName

UserNameOverMessage

Soap12WSAddressing10

WSHttpBinding + disable secure sessions and negotiation + SecurityMode.TransportWithMessageCredential + MessageCredentialType.UserName

Figure 3: Standard binding equivalent settings for common AssertEncryptionHttpBinding SecurityMode and MessageVersion settings.

Remember that the AssertEncryptionHttpBinding assumes the communication channel will be unencrypted, because the purpose of the binding is to wrap the use of the AssertEncryptionHttpTransportBindingElement to receive unencrypted credentials. As such, the SecurityMode property need only collect information about the type of credentials that will be used to authenticate.

 

Creating Binding Elements for AssertEncryptionHttpBinding

A binding type is the type through which the communication channel is built. This is done by constructing a collection of binding elements, including transport, message encoder, and other channel features, such as security. You can use pre-existing binding elements or custom binding elements to build the channel stack so long as there is a message encoder and a transport channel. I discussed this in my last article.

Aside from exposing properties listed in the previous section, the AssertEncryptionHttpBinding type also provides overrides for abstract members of the base binding type, and implements IBindingRuntimePreferences. Implementing IBindingRuntimePreferences is optional, yet common to most bindings. This contract is used to indicate if requests can be handled synchronously or asynchronously at the service. Usually asynchronous is preferred so the implementation of the read-only property, ReceiveSynchronously, usually reports False (as shown in Listing One).

AssertEncryptionHttpBinding provides an override for the read-only Scheme property, and for CreateBindingElements. Scheme always returns HTTP, as the purpose of the binding is to receive credentials without encryption. The implementation for CreateBindingElements is really the heart of this custom binding.

CreateBindingElements is called to build a collection of binding elements that will be used to build the channel stack. The binding relies on properties to select the appropriate binding elements, and to initialize properties on those binding elements. You should expose properties for any property you want to allow control over for the underlying binding elements. In Listing One you can see the complete implementation of CreateBindingElements. This list summarizes what is going on in there:

  • If message security is used, a SecurityBindingElement is created to support UserName credentials passed in the message, protected by the transport. CreateUserNameOverTransportBindingElement is the way to programmatically create this element for a CustomBinding.
  • Depending on the setting for MessageEncoding, the appropriate Text or Mtom message encoder is added to the binding elements collection.
  • The same transport binding element is always used (AssertEncryptionHttpTransportBindingElement).
  • If transport security is used, security is initialized on the transport binding element instead. This is handled by the private method GetTransport, which sets the transport s authentication scheme to AuthenticationSchemes.Basic if UserName credentials are to be passed in transport headers.

This binding exposes three constructors. Two are used to programmatically initialize the bindings using defaults for security, or explicitly passing a value for the SecurityMode property. The following illustrates how to construct the binding programmatically and initialize relevant settings to pass larger messages, arrays, and strings using SOAP 1.1 and Mtom encoding:

AssertEncryptionHttpBinding binding = new

 AssertEncryptionHttpBinding(

 AssertEncryptionHttpSecurityMode.UserNameOverMessage);

binding.MaxReceivedMessageSize = 100000;

binding.ReaderQuotas.MaxArrayLength = 100000;

binding.ReaderQuotas.MaxStringContentLength = 30000;

binding.ReceiveTimeout = new TimeSpan(0, 20, 0);

binding.MessageVersion = MessageVersion.Soap11;

binding.MessageEncoding = WSMessageEncoding.Mtom; 

Recall that the ReceiveTimeout is a property inherited from the binding base type, and that MessageVersion hides the base type implementation because it is read-only.

To configure the binding declaratively, I created a custom StandardBindingElement and StandardBindingCollectionElement, which I ll discuss next.

 

Declaratively Configuring AssertEncryptionHttpBinding

You must supply a custom binding configuration element to support declarative configuration for a custom binding. To achieve declarative configuration for AssertEncryptionHttpBinding I created the AssertEncryptionHttpBindingElement, which extends StandardBindingElement (as shown in Listing Two).

The following list breaks down the functionality of the custom binding configuration element and its base types:

  • At the core is the ConfigurationElement type, which provides serialization and deserialization functionality for any configuration element.
  • StandardBindingElement extends ConfigurationElement to add properties common to most bindings, including timeout properties (OpenTimeout, CloseTimeout, SendTimeout, ReceiveTimeout) and the Name property for naming the binding element.
  • AssertEncryptionHttpBindingElement exposes additional configuration properties, which are then used to configure the binding type, AssertEncryptionHttpBinding. Usually there is a synergy between the properties that a custom binding type exposes and custom configuration element properties (to support equivalent declarative configuration).

It helps to have a picture of the desired XML configuration in terms of elements and attributes before you determine the properties you ll expose on the binding configuration element type. Figure 4 shows examples of several configurations. Each example sets the various properties exposed by the binding: MaxReceivedMessageSize, MessageEncoding, MessageVersion, SecurityMode, and common values for ReaderQuotas.



 

   

     

   

   

     

   

   

     

   

 

 

Figure 4: Examples of declarative configuration for AssertEncryptionHttpBinding.

To achieve this configuration, the custom binding configuration element must expose a property for each setting and decorate it with the ConfigurationElementAttribute, as shown here for MaxReceivedMessageSize:

[ConfigurationProperty("maxReceivedMessageSize",

 DefaultValue = 0x10000L)]

[LongValidator(MinValue = 1L)]

public long MaxReceivedMessageSize

You will typically supply a name for the configuration element, as well as a default value. Optionally, you can use one of the predefined ConfigurationValidatorAttribute types, such as the LongValidatorAttribute used for MaxReceivedMessageSize.

In the case of ReaderQuotas, the property itself is also a type of ConfigurationElement (XmlDictionaryReaderQuotasElement), which in turn exposes properties decorated with the ConfigurationElementAttribute:

[ConfigurationProperty("readerQuotas")]

public XmlDictionaryReaderQuotasElement

 ReaderQuotas {get; set;}

public sealed class XmlDictionaryReaderQuotasElement :

 ConfigurationElement

{...}

You can create your own nested XML definitions for the binding configuration by referencing custom ConfigurationElement types as children.

The get and set implementation for configuration properties typically use the base ConfigurationElement indexer, as shown here for the MessageEncoding property (enumerations can simply be cast on return):

[ConfigurationProperty("messageEncoding", DefaultValue = 0)]

public WSMessageEncoding MessageEncoding

{

   get

   {

       return (WSMessageEncoding)base["messageEncoding"];

   }

   set

   {

       base["messageEncoding"] = value.ToString();

   }

}

Aside from defining configuration properties, the custom binding configuration element type also provides the following overrides:

  • BindingElementType: A read-only property override that should return the correct binding element type.
  • InitializeFrom: A method override that initializes the binding configuration element from a binding type instance.
  • ApplyConfiguration: A method override that initializes a binding type instance from configuration settings.
  • Properties: A read-only property override that builds a ConfigurationPropertyCollection with a list of properties for the base type indexer. Each property can have a name, type, and, optionally, a default value, a validator, and configuration options based on the ConfigurationPropertyOptions collection the latter of which is useful for marking required properties most frequently used.

ApplyConfiguration is called when you associate a declarative binding configuration with an endpoint, like those shown in Figure 4. A few more steps are required to trigger this association. First, a custom StandardBindingCollectionElement must be defined to associate the binding type with the custom binding configuration element type. Figure 5 shows the implementation for the AssertEncryptionHttpBindingCollectionElement, which extends StandardBindingCollectionElement.

public class AssertEncryptionHttpBindingCollectionElement:

 StandardBindingCollectionElement

{

 public const string BindingCollectionElementName =

   "assertEncryptionHttpBinding";

  public static AssertEncryptionHttpBindingCollectionElement

    GetBindingCollectionElement()

 {

   AssertEncryptionHttpBindingCollectionElement

     bindingCollectionElement = null;

   BindingsSection bindingsSection =

      ConfigurationManager.GetSection("system.serviceModel/bindings")

      as BindingsSection;

   if (bindingsSection != null)

   {

     bindingCollectionElement = bindingsSection[

      AssertEncryptionHttpBindingCollectionElement.BindingCollectionElementName]

      as AssertEncryptionHttpBindingCollectionElement;

   }

   return bindingCollectionElement;

 }

}

Figure 5: AssertEncryptionHttpBindingCollectionElement implementation.

Following suit with other implementations of standard binding collection elements, I exposed a static method (GetBindingCollectionElement) to do the work of loading the appropriate configuration section. This method is called by the custom binding configuration element during initialization.

Next, the section of must include a element that associates the bindings section with the custom StandardBindingElementCollection type. The following associates the elements shown in Figure 4 with the AssertEncryptionHttpBindingCollectionElement shown in Figure 5:



 

   

 

 

When the ServiceHost initializes endpoints that use declarations, AssertEncryptionHttpBindingCollectionElement is used to find the configuration element type to initialize with configuration values, and the correct Binding type to initialize from that configuration.

Note: You also can use a utility supplied with the WCF Samples in the Windows SDK, ConfigurationCodeGenerator.exe, to generate code to support declarative configuration of your custom bindings or binding elements.

 

Conclusion

In this two-article series I provided a practical example for creating a custom binding element, and one for creating a custom binding. My goal was to provide you with a simple example that did not dive into the depths of custom channel creation that involves channel listeners and channel factories which would take a lot more than a few short articles to describe effectively. Developers frequently need to customize existing binding elements or standard bindings in this way; this example has illustrated how easy it can be to create and configure custom binding elements and custom bindings.

There are some very rich examples of custom bindings, binding elements, channel listeners, and channel factories available in the Windows SDK for .NET 3.5, including the popular chunking channel and router examples. See my code download for information on where to find those specific samples in addition to my own. 

In the next article for this column I ll begin to explore new features forthcoming in WCF 4.0. Get ready!

 

Download the samples for this article at http://www.dasblonde.net/downloads/asppromar09.zip.

 

Begin Listing One AssertEncryptionHttpBinding implementation

public class AssertEncryptionHttpBinding :

 Binding, IBindingRuntimePreferences

{

 public AssertEncryptionHttpSecurityMode

   SecurityMode { get; set; }

 public WSMessageEncoding MessageEncoding {get; set;}

 public new MessageVersion MessageVersion

 {

   get

   {

     if (this.MessageEncoding == WSMessageEncoding.Text)

         return this.TextEncoding.MessageVersion;

     else

       return this.MtomEncoding.MessageVersion;

   }

   set

   {

     this.TextEncoding.MessageVersion = value;

     this.MtomEncoding.MessageVersion = value;

   }

 }

 public long MaxReceivedMessageSize

 {

   get

   {

     return this.Transport.MaxReceivedMessageSize;

   }

   set

   {

     this.Transport.MaxReceivedMessageSize = value;

   }

 }

 public XmlDictionaryReaderQuotas ReaderQuotas

 {

   get

   {

     if (this.MessageEncoding == WSMessageEncoding.Text)

       return this.TextEncoding.ReaderQuotas;

     else

       return this.MtomEncoding.ReaderQuotas;

   }

   set

   {

     value.CopyTo(this.TextEncoding.ReaderQuotas);

     value.CopyTo(this.MtomEncoding.ReaderQuotas);

   }

 }

 private AssertEncryptionHttpTransportBindingElement

   Transport { get; set; }

 private TextMessageEncodingBindingElement

   TextEncoding { get; set; }

 private MtomMessageEncodingBindingElement

   MtomEncoding { get; set; }

 public AssertEncryptionHttpBinding()

   : this(AssertEncryptionHttpSecurityMode.None)

 {

 }

 public AssertEncryptionHttpBinding(

  AssertEncryptionHttpSecurityMode securityMode)

 {

   this.SecurityMode = securityMode;

   this.MessageEncoding = WSMessageEncoding.Text;

   this.TextEncoding = new

     TextMessageEncodingBindingElement();

   this.MtomEncoding = new

     MtomMessageEncodingBindingElement();

   this.MessageVersion=

    MessageVersion.Soap12WSAddressing10;

   this.Transport = new

     AssertEncryptionHttpTransportBindingElement();

 }

 public AssertEncryptionHttpBinding(string

   configurationName): this()

 {

   AssertEncryptionHttpBindingElement bindingElement =

    AssertEncryptionHttpBindingCollectionElement.

    GetBindingCollectionElement().Bindings[configurationName]

    as AssertEncryptionHttpBindingElement;

   if (bindingElement == null)

     throw new ConfigurationErrorsException(

      string.Format("Binding configuration element

       missing: {0} in {1}", configurationName,

       AssertEncryptionHttpBindingCollectionElement.

      BindingCollectionElementName));

   bindingElement.ApplyConfiguration(this);

 }

 public override BindingElementCollection

   CreateBindingElements()

 {

   BindingElementCollection bindingElements =

     new BindingElementCollection();

   // if passing credentials via message security,

   // add a security element

   TransportSecurityBindingElement

     transportSecurityElement = null;

   if (this.SecurityMode ==

     AssertEncryptionHttpSecurityMode.UserNameOverMessage)

   {

     transportSecurityElement = SecurityBindingElement.

      CreateUserNameOverTransportBindingElement();

   }

   if (transportSecurityElement != null)

     bindingElements.Add(transportSecurityElement);

   // add a message encoder element

   if (this.MessageEncoding == WSMessageEncoding.Text)

     bindingElements.Add(this.TextEncoding);

   else if (this.MessageEncoding == WSMessageEncoding.Mtom)

     bindingElements.Add(this.MtomEncoding);

   // add a transport element

   bindingElements.Add(this.GetTransport());

   return bindingElements;

 }

 private TransportBindingElement GetTransport()

 {

   if (this.SecurityMode ==

    AssertEncryptionHttpSecurityMode.UserNameOverTransport)

   {

     this.Transport.AuthenticationScheme =

       System.Net.AuthenticationSchemes.Basic;

    }

   return this.Transport;

 }

 public override string Scheme

 {

   get { return this.Transport.Scheme; }

 }

 #region IBindingRuntimePreferences Members

 public bool ReceiveSynchronously

 {

   get { return false; }

 }

 #endregion

}

End Listing One

 

Begin Listing Two AssertEncryptionHttpBindingElement implementation

public class AssertEncryptionHttpBindingElement:

 StandardBindingElement

{

  [ConfigurationProperty("messageEncoding",

  DefaultValue = 0)]

 public WSMessageEncoding MessageEncoding

 {

   get

   {

     return (WSMessageEncoding)base["messageEncoding"];

   }

   set

   {

     base["messageEncoding"] = value.ToString();

   }

 }

  [ConfigurationProperty("maxReceivedMessageSize",

   DefaultValue = 0x10000L), LongValidator(MinValue = 1L)]

 public long MaxReceivedMessageSize

 {

   get

   {

     return (long)base["maxReceivedMessageSize"];

   }

   set

   {

     base["maxReceivedMessageSize"] = value;

   }

 }

 public const string DefaultMessageVersion =

   "Soap11WSAddressing10";

  [ConfigurationProperty("messageVersion", DefaultValue =

   AssertEncryptionHttpBindingElement.DefaultMessageVersion)]

 public MessageVersion MessageVersion

 {

   get

   {

     string messageVersion = (string)base["messageVersion"];

     System.Reflection.PropertyInfo propertyInfo =

       typeof(MessageVersion).GetProperty(messageVersion);

     return (MessageVersion)propertyInfo.GetValue(null, null);

   }

   set

   {

     base["messageVersion"] = value.ToString();

   }

 }

  [ConfigurationProperty("readerQuotas")]

 public XmlDictionaryReaderQuotasElement ReaderQuotas

 {

   get

   {

     return (XmlDictionaryReaderQuotasElement)base[

      "readerQuotas"];

   }

 }

  [ConfigurationProperty("securityMode", DefaultValue =

   AssertEncryptionHttpSecurityMode.None)]

 public AssertEncryptionHttpSecurityMode SecurityMode

 {

   get

   {

     return (AssertEncryptionHttpSecurityMode)base[

      "securityMode"];

   }

   set

   {

     base["securityMode"] = value;

   }

 }

 protected override Type BindingElementType

 {

   get { return typeof(AssertEncryptionHttpBinding); }

 }

 protected override void InitializeFrom(

  System.ServiceModel.Channels.Binding binding)

 {

   base.InitializeFrom(binding);

   AssertEncryptionHttpBinding assertEncryptionHttpBinding

      = (AssertEncryptionHttpBinding)binding;

   this.MessageEncoding =

    assertEncryptionHttpBinding.MessageEncoding;

   this.MessageVersion =

    assertEncryptionHttpBinding.MessageVersion;

   this.MaxReceivedMessageSize =

     assertEncryptionHttpBinding.MaxReceivedMessageSize;

   this.SecurityMode =

     assertEncryptionHttpBinding.SecurityMode;

 }

 protected override void OnApplyConfiguration(

  System.ServiceModel.Channels.Binding binding)

 {

   AssertEncryptionHttpBinding assertEncryptionHttpBinding

     = (AssertEncryptionHttpBinding)binding;

   assertEncryptionHttpBinding.MessageEncoding =

     this.MessageEncoding;

   assertEncryptionHttpBinding.MessageVersion =

     this.MessageVersion;

   if (this.ReaderQuotas != null)

   {

     if (this.ReaderQuotas.MaxDepth != 0)

     {

       assertEncryptionHttpBinding.ReaderQuotas.MaxDepth =

         this.ReaderQuotas.MaxDepth;

     }

     if (this.ReaderQuotas.MaxStringContentLength != 0)

     {

       assertEncryptionHttpBinding.ReaderQuotas.

        MaxStringContentLength = this.ReaderQuotas.

        MaxStringContentLength;

       }

       if (this.ReaderQuotas.MaxArrayLength != 0)

       {

         assertEncryptionHttpBinding.ReaderQuotas.

          MaxArrayLength = this.ReaderQuotas.

          MaxArrayLength;

       }

       if (this.ReaderQuotas.MaxBytesPerRead != 0)

       {

         assertEncryptionHttpBinding.ReaderQuotas.

          MaxBytesPerRead = this.ReaderQuotas.

          MaxBytesPerRead;

        }

       if (this.ReaderQuotas.MaxNameTableCharCount != 0)

       {

         assertEncryptionHttpBinding.ReaderQuotas.

          MaxNameTableCharCount = this.ReaderQuotas.

          MaxNameTableCharCount;

       }

     }

     assertEncryptionHttpBinding.SecurityMode =

      this.SecurityMode;

 }

 private ConfigurationPropertyCollection m_properties;

 protected override

   ConfigurationPropertyCollection Properties

 {

   get

   {

     ConfigurationPropertyCollection properties = null;

     if (this.m_properties == null)

     {

       properties = base.Properties;

       properties.Add(new ConfigurationProperty(

        "messageEncoding", typeof(WSMessageEncoding),

        WSMessageEncoding.Text, null, null,

        ConfigurationPropertyOptions.None));

       properties.Add(new ConfigurationProperty(

        "maxReceivedMessageSize", typeof(long), 0x10000L,

        null, new LongValidator(1L, 0x7fffffffffffffffL,

        false), ConfigurationPropertyOptions.None));

       properties.Add(new ConfigurationProperty(

        "messageVersion", typeof(string),

        AssertEncryptionHttpBindingElement.

        DefaultMessageVersion, null, null,

         ConfigurationPropertyOptions.None));

       properties.Add(new ConfigurationProperty(

        "readerQuotas", typeof(

        XmlDictionaryReaderQuotasElement), null, null,

         null, ConfigurationPropertyOptions.None));

       properties.Add(new ConfigurationProperty(

        "securityMode", typeof(

        AssertEncryptionHttpSecurityMode),

        AssertEncryptionHttpSecurityMode.None, null,

         null, ConfigurationPropertyOptions.None));

       this.m_properties = properties;

     }

     return this.m_properties;

   }

 }

}

End Listing Two

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish