Content-based routing

Apr 12, 2008 at 11:00 AM
How can I change the channel moniker based on the message content? I want to redirect calls based on a header set within a policy behavior earliler in the stack. I got 3 physical endpoints, all the same, but on different URIs. Based on the header information, different endpoints will be served.

/Casper
Developer
Apr 14, 2008 at 10:37 PM
Casper-

You'd need to define your own channel moniker so you can provide the appropriate address when the channel is constructed. For the 6.2 release we don't have much guidance, but I've been working on some samples that we will try to post soon.

If you are adventurous, you can explore implementing the IChannelBuilder interface located in the Microsoft.MSE.Runtime.Channels assembly. Note that this will be changing in our next release so you may wish to wait. (you'll need to derive from Binding rather than implement the MSE interface).

You'd need to make sure IChannelBuilder.GetChannelMetadata() returns a ChannelModelElement that has the desired address.
Within this method you should be able to access OperationContext.Current to inspect the incomming message header and decide what address to return.

You can then change the channel moniker xml on your operation version to point to your class rather than the default one (this is just XAML). You'll need to be familiar with XAML in order to do so. Use Reflector to examine Microsoft.MSE.Runtime.Channels.ChannelModel if you want to see how to our default implementation works.



casperd wrote:
How can I change the channel moniker based on the message content? I want to redirect calls based on a header set within a policy behavior earliler in the stack. I got 3 physical endpoints, all the same, but on different URIs. Based on the header information, different endpoints will be served.

/Casper

Apr 15, 2008 at 9:01 PM
Thanks.

That was pretty straight forward (had some issues with xaml). I tested it on the sample calc service and here is the channel moniker:

<chr:CustomHeaderRoutingModel xmlns:chr="clr-namespace:MSE.Channels;assembly=CustomHeaderRouting" xmlns:mse="http://microsoft.com/mse/2007/runtime/channelModel" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<mse:ChannelModelElement>
<mse:ChannelModelElement.Address>http://machine:8080/CalculatorWCF/Calculator/Basic</mse:ChannelModelElement.Address>
<mse:ChannelModelElement.Action>http://mse.testservices.com/wcf/calculator/ICalculator/AddIntegers</mse:ChannelModelElement.Action>
</mse:ChannelModelElement>
</chr:CustomHeaderRoutingModel>

I got the message from the OperationContext.Current.RequestContext.RequestMessage and was able to substitute "machine" within the moniker with the appropriate host name. Will work on this to make it more configurable. Great stuff!


botto wrote:
Casper-

You'd need to define your own channel moniker so you can provide the appropriate address when the channel is constructed. For the 6.2 release we don't have much guidance, but I've been working on some samples that we will try to post soon.

If you are adventurous, you can explore implementing the IChannelBuilder interface located in the Microsoft.MSE.Runtime.Channels assembly. Note that this will be changing in our next release so you may wish to wait. (you'll need to derive from Binding rather than implement the MSE interface).

You'd need to make sure IChannelBuilder.GetChannelMetadata() returns a ChannelModelElement that has the desired address.
Within this method you should be able to access OperationContext.Current to inspect the incomming message header and decide what address to return.

You can then change the channel moniker xml on your operation version to point to your class rather than the default one (this is just XAML). You'll need to be familiar with XAML in order to do so. Use Reflector to examine Microsoft.MSE.Runtime.Channels.ChannelModel if you want to see how to our default implementation works.



casperd wrote:
How can I change the channel moniker based on the message content? I want to redirect calls based on a header set within a policy behavior earliler in the stack. I got 3 physical endpoints, all the same, but on different URIs. Based on the header information, different endpoints will be served.

/Casper


Developer
Apr 15, 2008 at 11:38 PM
I'm glad to see you were able to get it working so quickly.

Using XAML to define the moniker also provides a means to store property values for your moniker class to use when constructing the WCF ChannelFactory. You could use this to store the mappings of your specific header values to host names. If appropriate, you would be able to have different mappings for different operation versions. This is a very simplistic and decentralized way to store configuration, but is appropriate in many scenarios.

The channel moniker is a great extensibility point giving you complete control over how to invoke your services.



casperd wrote:
Thanks.

That was pretty straight forward (had some issues with xaml). I tested it on the sample calc service and here is the channel moniker:

<chr:CustomHeaderRoutingModel xmlns:chr="clr-namespace:MSE.Channels;assembly=CustomHeaderRouting" xmlns:mse="http://microsoft.com/mse/2007/runtime/channelModel" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<mse:ChannelModelElement>
<mse:ChannelModelElement.Address>http://machine:8080/CalculatorWCF/Calculator/Basic</mse:ChannelModelElement.Address>
<mse:ChannelModelElement.Action>http://mse.testservices.com/wcf/calculator/ICalculator/AddIntegers</mse:ChannelModelElement.Action>
</mse:ChannelModelElement>
</chr:CustomHeaderRoutingModel>

I got the message from the OperationContext.Current.RequestContext.RequestMessage and was able to substitute "machine" within the moniker with the appropriate host name. Will work on this to make it more configurable. Great stuff!


botto wrote:
Casper-

You'd need to define your own channel moniker so you can provide the appropriate address when the channel is constructed. For the 6.2 release we don't have much guidance, but I've been working on some samples that we will try to post soon.

If you are adventurous, you can explore implementing the IChannelBuilder interface located in the Microsoft.MSE.Runtime.Channels assembly. Note that this will be changing in our next release so you may wish to wait. (you'll need to derive from Binding rather than implement the MSE interface).

You'd need to make sure IChannelBuilder.GetChannelMetadata() returns a ChannelModelElement that has the desired address.
Within this method you should be able to access OperationContext.Current to inspect the incomming message header and decide what address to return.

You can then change the channel moniker xml on your operation version to point to your class rather than the default one (this is just XAML). You'll need to be familiar with XAML in order to do so. Use Reflector to examine Microsoft.MSE.Runtime.Channels.ChannelModel if you want to see how to our default implementation works.



casperd wrote:
How can I change the channel moniker based on the message content? I want to redirect calls based on a header set within a policy behavior earliler in the stack. I got 3 physical endpoints, all the same, but on different URIs. Based on the header information, different endpoints will be served.

/Casper



Apr 16, 2008 at 1:19 PM
Great! You mentioned the next release. When can we expect those bits?

Btw. When deriving System.ServiceModel.Channels.Binding, will I have to override any methods or just adding the metadata properties (address, action)?

-Casper


botto wrote:
I'm glad to see you were able to get it working so quickly.

Using XAML to define the moniker also provides a means to store property values for your moniker class to use when constructing the WCF ChannelFactory. You could use this to store the mappings of your specific header values to host names. If appropriate, you would be able to have different mappings for different operation versions. This is a very simplistic and decentralized way to store configuration, but is appropriate in many scenarios.

The channel moniker is a great extensibility point giving you complete control over how to invoke your services.



casperd wrote:
Thanks.

That was pretty straight forward (had some issues with xaml). I tested it on the sample calc service and here is the channel moniker:

<chr:CustomHeaderRoutingModel xmlns:chr="clr-namespace:MSE.Channels;assembly=CustomHeaderRouting" xmlns:mse="http://microsoft.com/mse/2007/runtime/channelModel" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<mse:ChannelModelElement>
<mse:ChannelModelElement.Address>http://machine:8080/CalculatorWCF/Calculator/Basic</mse:ChannelModelElement.Address>
<mse:ChannelModelElement.Action>http://mse.testservices.com/wcf/calculator/ICalculator/AddIntegers</mse:ChannelModelElement.Action>
</mse:ChannelModelElement>
</chr:CustomHeaderRoutingModel>

I got the message from the OperationContext.Current.RequestContext.RequestMessage and was able to substitute "machine" within the moniker with the appropriate host name. Will work on this to make it more configurable. Great stuff!


botto wrote:
Casper-

You'd need to define your own channel moniker so you can provide the appropriate address when the channel is constructed. For the 6.2 release we don't have much guidance, but I've been working on some samples that we will try to post soon.

If you are adventurous, you can explore implementing the IChannelBuilder interface located in the Microsoft.MSE.Runtime.Channels assembly. Note that this will be changing in our next release so you may wish to wait. (you'll need to derive from Binding rather than implement the MSE interface).

You'd need to make sure IChannelBuilder.GetChannelMetadata() returns a ChannelModelElement that has the desired address.
Within this method you should be able to access OperationContext.Current to inspect the incomming message header and decide what address to return.

You can then change the channel moniker xml on your operation version to point to your class rather than the default one (this is just XAML). You'll need to be familiar with XAML in order to do so. Use Reflector to examine Microsoft.MSE.Runtime.Channels.ChannelModel if you want to see how to our default implementation works.



casperd wrote:
How can I change the channel moniker based on the message content? I want to redirect calls based on a header set within a policy behavior earliler in the stack. I got 3 physical endpoints, all the same, but on different URIs. Based on the header information, different endpoints will be served.

/Casper




Developer
Apr 17, 2008 at 8:59 PM
The plan for the new way to extend the channel moniker would require overriding Binding.BuildChannelFactory<TChannel>(BindingParameterCollection parameters). This method returns the ChannelFactory the MSE will use (similar to how you implemented the interface for 6.2). As for the metadata properties, it would be up to your moniker to have/use any custom properties it needs to aid in creating the proper ChannelFactory (action and address are likely candidates). We don't make any assumptions about new monikers having a set of known properties.

The thinking with this approach is around composite bindings. The Binding you associate with the Operation Version's Channel Type is passed in as an item in the parameters argument of the moniker's BuildChannelFactory method. This allows the moniker (which itself is now a binding) to construct the proper ChannelFactory that may use all/part/none of the binding that was passed in as an argument.

Guidance and samples around custom bindings and monikers is something we are actively working on.

As for the timing on our next release, stay tuned for more information.


casperd wrote:
Great! You mentioned the next release. When can we expect those bits?

Btw. When deriving System.ServiceModel.Channels.Binding, will I have to override any methods or just adding the metadata properties (address, action)?

-Casper


botto wrote:
I'm glad to see you were able to get it working so quickly.

Using XAML to define the moniker also provides a means to store property values for your moniker class to use when constructing the WCF ChannelFactory. You could use this to store the mappings of your specific header values to host names. If appropriate, you would be able to have different mappings for different operation versions. This is a very simplistic and decentralized way to store configuration, but is appropriate in many scenarios.

The channel moniker is a great extensibility point giving you complete control over how to invoke your services.



casperd wrote:
Thanks.

That was pretty straight forward (had some issues with xaml). I tested it on the sample calc service and here is the channel moniker:

<chr:CustomHeaderRoutingModel xmlns:chr="clr-namespace:MSE.Channels;assembly=CustomHeaderRouting" xmlns:mse="http://microsoft.com/mse/2007/runtime/channelModel" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<mse:ChannelModelElement>
<mse:ChannelModelElement.Address>http://machine:8080/CalculatorWCF/Calculator/Basic</mse:ChannelModelElement.Address>
<mse:ChannelModelElement.Action>http://mse.testservices.com/wcf/calculator/ICalculator/AddIntegers</mse:ChannelModelElement.Action>
</mse:ChannelModelElement>
</chr:CustomHeaderRoutingModel>

I got the message from the OperationContext.Current.RequestContext.RequestMessage and was able to substitute "machine" within the moniker with the appropriate host name. Will work on this to make it more configurable. Great stuff!


botto wrote:
Casper-

You'd need to define your own channel moniker so you can provide the appropriate address when the channel is constructed. For the 6.2 release we don't have much guidance, but I've been working on some samples that we will try to post soon.

If you are adventurous, you can explore implementing the IChannelBuilder interface located in the Microsoft.MSE.Runtime.Channels assembly. Note that this will be changing in our next release so you may wish to wait. (you'll need to derive from Binding rather than implement the MSE interface).

You'd need to make sure IChannelBuilder.GetChannelMetadata() returns a ChannelModelElement that has the desired address.
Within this method you should be able to access OperationContext.Current to inspect the incomming message header and decide what address to return.

You can then change the channel moniker xml on your operation version to point to your class rather than the default one (this is just XAML). You'll need to be familiar with XAML in order to do so. Use Reflector to examine Microsoft.MSE.Runtime.Channels.ChannelModel if you want to see how to our default implementation works.



casperd wrote:
How can I change the channel moniker based on the message content? I want to redirect calls based on a header set within a policy behavior earliler in the stack. I got 3 physical endpoints, all the same, but on different URIs. Based on the header information, different endpoints will be served.

/Casper