How to change the WCF message encoding of NETTCP in programming?

I have a custom intranet application with no interoperability requirements. We programmatically construct a NetTcp channel in duplex mode to pass messages. We want to change the message encoding, but we can’t figure it out How to achieve this.

The approach we took (failed) is to extend NetTcpBinding to a new class called LeanTcpBinding, as shown below:

internal class LeanTcpBinding: NetTcpBinding
{
private static readonly ILog _log =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

public override BindingElementCollection CreateBindingElements()
{
BindingElementCollection bindingElementCollection = base.CreateBindingElements();
BindingElement encodingElement = bindingElementCollection.FirstOrDefault(
bindingElement => bindingElement is BinaryMessageEncodingBindingElement);< br /> if (encodingElement != null)
{
int index = bindingElementCollection.IndexOf(encodingElement);
bindingElementCollection.RemoveAt(index);
bindingElementCollection.Insert (index, new LeanBinaryMessageEncodingBindingElement());
}
else
{
_log.Warn("Encoding not found");
}

return bindingElementCollection;
}
}

Obviously, we tried to replace the default BinaryMessageEncodingBindingElement with our own. Just to get started, LeanBinaryMessageEncodingBindingElement is an extension of BinaryMessageEncodingBindingElement, as shown below:

internal class LeanBinaryMessageEncodingBindingElement: MessageEncodingBindingElement
{
private readonly BinaryMessageEncodingBindingElement _bindingElement;

///
// / Initializes a new instance of the class.
///
public LeanBinaryMessageEncodingBindingElement()
{
_bindingElement = new BinaryMessageEncodingBindingElement();
}
< br /> ///
/// Initializes a new instance of the class.
///
/// The binding eleme nt.
public LeanBinaryMessageEncodingBindingElement(BinaryMessageEncodingBindingElement bindingElement)
{
_bindingElement = bindingElement;
}

///
/// Initializes a new instance of the class.
///
/// The element to be cloned.
/// The binding element.
public LeanBinaryMessageEncodingBindingElement(MessageEncodingBindingElement elementToBeCloned, BinaryMessageEncodingBindingElement bindingElement)
: base(elementToBeCloned)
{
_bindingElement = bindingElement;
}

///
/// When overridden in a derived class, returns a copy of the binding element object.
///
///
/// A object that is a deep clone of the original.
///
public override BindingElement Clone()
{
return new LeanBinaryMessageEncodingBindingElement(
(BinaryMessageEncodingBindingElement)_bindingElement.Clone());
}

///
/// When overridden in a derived class, creates a factory for producing message encoders.
///
///
/// The used to produce message encoders.
///
public override MessageEncoderFactory CreateMessageEncoderFactory()< br /> {
return new LeanBinaryMessageEncoderFactory(_bindingElement.CreateMessageEncoderFactory());
}

///
/// When overridden in a derived class, gets or sets the message version that can be handled by the message encoders produced by the message encoder factory.
///
///
/// The used by the encoders produced by the message encoder factory.
///
public override MessageVersion MessageVersion
{
get {return _bindingElement.MessageVersion; }
set {_bindingElement.MessageVersion = value; }
}
}

When I try to use binding , It does exactly what I think it should do… It replaces BinaryMessageEncodingBindingElement. However, even if messages are exchanged through the channel, I have never accepted any calls to LeanBinaryMessageEncodingBindingElement.CreateMessageEncoderFactory().

Any suggestions for doing this correctly?

Kenny Wolf clarified the missing content and recorded it in the following blog post.

Boilerplate code for custom Encoder Binding Elements

The problem with impatience is that, by default, MessageEncoderBindingElement does not add itself to the binding of the context As a result, when the transmission went to find the MessageEncoderBindingElement later, it could not find the one I (or you) created, and I noticed the silent failure in the original post.

Unfortunately, You must override all CanBuildXXX and BuildXXX methods as follows to ensure that binding elements are added to the binding parameters of the context.


public override bool CanBuildChannelFactory( BindingContext context)
{
if (context == null) {
throw new ArgumentNullException("context");
}

context.BindingParameters. Add(this);
return context.CanBuildInnerChannelFactory();
}

public override bool CanBuildChannelListener(BindingContext context)
{
if (context = = null) {
throw new ArgumentNullException("context");
}

context.BindingParame ters.Add(this);
return context.CanBuildInnerChannelListener();
}

public override IChannelFactory BuildChannelFactory(BindingContext context)
{
if ( context == null) {
throw new ArgumentNullException("context");
}

context.BindingParameters.Add(this);
return context.BuildInnerChannelFactory( );
}

public override IChannelListener BuildChannelListener(BindingContext context)
{
if (context == null) {
throw new ArgumentNullException("context ");
}

context.BindingParameters.Add(this);
return context.BuildInnerChannelListener();
}

< /p>

I have a custom intranet application that has no interoperability requirements. We programmatically construct a NetTcp channel in duplex mode to pass messages. We want to change the message encoding, but can’t figure out how to achieve this.

The approach we took (failure) is to extend NetTcpBinding to a new class called LeanTcpBinding, as shown below Show:

internal class LeanTcpBinding: NetTcpBinding
{
private static readonly ILog _log =
LogManager.GetLogger(System.Reflection.MethodBase. GetCurrentMethod().DeclaringType);

public override BindingElementCollection CreateBindingElements()
{
BindingElementCollection bindingElementCollection = base.CreateBindingElements();
BindingElement encodingElement = bindingElementCollection.FirstOrDefault(
bindingElement => bindingElement is BinaryMessageEncodingBindingElement);
if (encodingElement != null)
{
int index = bindingElementCollection.IndexOf(encodingElement);
bindingElementCollection.RemoveAt( index);
bindingElementCollection.Insert(index, new LeanBinaryMessageEncodingBindingElement());
}
else
{
_log.Warn("Encoding not found");< br /> }
return bindingElementCollection;
}
}

Obviously, we are trying to replace the default BinaryMessageEncodingBindingElement with our own. Just to get started, LeanBinaryMessageEncodingBindingElement is an extension of BinaryMessageEncodingBindingElement, as shown below :

internal class LeanBinaryMessageEncodingBindingElement: MessageEncodingBindingElement
{
private readonly BinaryMessageEncodingBindingElement _bindingElement;

///
/ // Initializes a new instance of the class.
///
public LeanBinaryMessageEncodingBindingElement()
{
_bindingElement = new BinaryMessageEncodingBindingElement();
}

///
/// Initializes a new instance of the class.
///
/// The binding element.
public LeanBinaryMessageEncodingBindingElement(BinaryMessageEncodingBindingElement bindingElement)
{
_bindingElement = bindingElemen t;
}

///
/// Initializes a new instance of the class.
///
/// The element to be cloned.
/// The binding element.
public LeanBinaryMessageEncodingBindingElement(MessageEncodingBindingElement elementToBeCloned, BinaryMessageEncodingBindingElement bindingElement)
: base(elementToBeCloned)
{
_bindingElement = bindingElement;< br /> }

///
/// When overridden in a derived class, returns a copy of the binding element object.
///
/ //
/// A object that is a deep clone of the original.
///
public override BindingElement Clone()
{
return new LeanBinaryMessageEncodingBindingElement(
(BinaryMessageEncodingBindingElement)_bindingElement.Clone());
}

///
/ // When overridden in a derived class, creates a factory for producing message encoders.
///
///
/// The used to produce message encoders.
/ //
public override MessageEncoderFactory CreateMessageEncoderFactory()
{
return new LeanBinaryMessageEncoderFactory(_bindingElement.CreateMessageEncoderFactory());
}

///
/// When overridden in a derived class, gets or sets the message version that can be handled by the message encoders produced by the message encoder factory.
///
///
/// The used by the encoders produced by the message encoder factory.
///
public override MessageVersion MessageVersion
{
get {return _bindingElement.MessageVersion; }
set {_bindingElement.MessageVersion = value; }
}
}

When I try to use the binding, it completely presses As I think it should do… it replaces BinaryMessageEncodingBindingElement. However, even if messages are exchanged through the channel, I have never accepted any calls to LeanBinaryMessageEncodingBindingElement.CreateMessageEncoderFactory().

Anyone has any ideas on how to do it correctly Any suggestions for this?

Kenny Wolf clarified the missing content and recorded it in the following blog post.

http: //kennyw.com/?p=170

The problem with impatience is that, by default, MessageEncoderBindingElement does not add itself to the binding parameters of the context. As a result, when the transmission is found later When MessageEncoderBindingElement, it can’t find the one I (or you) created, and I noticed the silent failure in the original post.

Unfortunately, you have to override all CanBuildXXX and BuildXXX methods as follows, To ensure that the binding element is added to the binding parameters of the context.


public override bool CanBuildChannelFactory(BindingContext context)
{
if (context == null) {
throw new ArgumentNullException("context");
}

context.BindingParameters.Add(this);
return context. CanBuildInnerChannelFactory();
}

public override bool CanBuildChannelListener(BindingContext context)
{
if (context == null) {
throw new ArgumentNullException( "context");
}

context.BindingParameters.Add(this);
return context.CanBuild InnerChannelListener();
}

public override IChannelFactory BuildChannelFactory(BindingContext context)
{
if (context == null) {
throw new ArgumentNullException( "context");
}

context.BindingParameters.Add(this);
return context.BuildInnerChannelFactory();
}

public override IChannelListener BuildChannelListener(BindingContext context)
{
if (context == null) {
throw new ArgumentNullException("context");
}

context.BindingParameters.Add(this);
return context.BuildInnerChannelListener();
}

Leave a Comment

Your email address will not be published.