Extending WCF: How to dynamically change the listening Uri in the custom binding element?

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives

By default the listening uri of one service can be either specified in the configuration file or programmatically by adding of the endpoint. For example, next code snoippet shows how to host the service HelloService : IHelloWorld at the base address and localhost and port 5555.

 

The second line register the listening at the localhost but at the port 4444, by using of WSHttpBinding.

 

ServiceHost host = new ServiceHost(typeof(HelloService), new Uri(http://localhost:5555/daenet));

          

host.AddServiceEndpoint(typeof(IHelloWorld), new WSHttpBinding(), "http://localhost:4444/daenet");

 

 

By implementing of the cutom binding element in WCF, you have a possibility to dynamically change the listening URI of the service. In this case there is custom binding, which derives for example from BindingElement (seee example bellow).

In the method BuildChannelListener the context instance can be used to change the URI. Note, that after this change all other channels (binding elements listener.InnerChannelListener) on the stack will deal with the new URI.

 

Following code-snippet show how to change the listening URI in the custom binding element.

 

public class MyBindingElement : BindingElement{

 

. . .

 

public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context){

      MyListener<TChannel> listener =

      new MyListener<TChannel>(this, context);

          

      listener.InnerChannelListener =

      context.BuildInnerChannelListener<TChannel>();

           

      context.ListenUriBaseAddress = new Uri(“http://localhost:3333/daenet);

     

      return listener;

 }   

 

. . .  

}

 

However, there is a small problem with this approach. When the client sends messages to the server, the are routed to the endpont with this original URI.

For example the original URI was uri1, and you have changed it to uri2. In that case all messages sent from client are routed to the uri1, because client possibly does not knows anything about the new address.

If so you have to change the destination address of the message (stored in the message.Headers.To property) to the originaly uri (uri1). If this is not done the Service Model will not invoke the required operation (defined by action header).

 

The changing of the destination of message can be done in any of method, which receives the message. In thext example I used the method EndTryReceiveRequest.

 

public bool EndTryReceiveRequest(IAsyncResult result, out IRequestContext requestContext){

 

IRequestContext innerRequestContext;

if (this.InnerChannel.EndTryReceiveRequest(result, out innerRequestContext))

{

      innerRequestContext.RequestMessage.Headers.To = new Uri(“uri2”);

     return true;

 }

 else

 {

      requestContext = null;

      return false;

 }

}

 


Posted Jul 27 2006, 04:31 PM by Damir Dobric
Filed under:
developers.de is a .Net Community Blog powered by daenet GmbH.