Using IContextChannel Extensions to Store Custom Data
Posted by Dan Rigsby on September 21st, 2008
Wcf offers numerous extensibility points. The best example of this is how the REST extensions were added in .Net 3.5. Nothing was rewritten. The entire Web Programming Model was built on the Wcf extensibility points and provided as an additional library that could be included in your projects(System.ServiceModel.Web). We have looked at a couple of the extensions points on this blog in the past (ObservableServiceHost & Extending InstanceContext). Another extension point is an IContextChannel Extension. This type of extension can be used for many things. Like any other IExtension, there is an Attach method and Detach methods that are called when working with the target object. In our case, the target object is an IContextChannel. You can use this to “extend” the incoming channel and “attach” information to it. This extended data isn’t available to the clients and is stored on the server only. You could use this to store a variety of data.
In our example, we are going to store a custom connection Id on the channel in the service. Usually you can uniquely identify a client by the SessionId, but occasionally you may want to use your own custom Id or just store some additional information on the channel.
Creating an IContextChannel Extension
ConnectionIdExtension
The extension itself is very straight forward. We can either store the ConnectionId in the object before it is attached to the channel, or if the ConnectionId is null, then a new one will be created when it is attached to the Channel.
public class ConnectionIdExtension : IExtension<IContextChannel> { private string m_ConnectionId = String.Empty; public string ConnectionId { get { return m_ConnectionId; } set { m_ConnectionId = value; } } public ConnectionIdExtension() { } public ConnectionIdExtension( string connectionId) { m_ConnectionId = connectionId; } #region IExtension<IContextChannel> Members public void Attach(IContextChannel owner) { // If there is no connectionId, create one if (String.IsNullOrEmpty(m_ConnectionId)) { m_ConnectionId = Guid.NewGuid().ToString(); } } public void Detach(IContextChannel owner) { } #endregion IExtension<IContextChannel> Members }
Attaching ConnectionIdExtension in an Operation
For our example service, we just have a method that returns the ConnectionId. It firsts checks the extensions collection on the channel to see if there is a ConnectionIdExtension applied. If there isn’t, a new one is created and added to the extensions collection.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)] public class MyService : IMyService { public string GetConnectionId() { IContextChannel channel = OperationContext.Current.Channel; ConnectionIdExtension connectionIdExtension = channel.Extensions.Find<ConnectionIdExtension>(); if (connectionIdExtension == null) { connectionIdExtension = new ConnectionIdExtension(); channel.Extensions.Add(connectionIdExtension); } return connectionIdExtension.ConnectionId; } }
Calling the Service and Observing the Behavior
If you use the WcfTestClient to test this method, you should see the same ConnectionId being used for each and every call from the client. However, if you select the “Start a new proxy” option on the client, then the Id will be different with each call. This option tells the client to create a new proxy instance with each call, so there is a new connection being used.
You can download a complete sample of the code discussed in this article here: http://www.danrigsby.com/Files/Rigsby.ChannelContext.zip

















September 22nd, 2008 at 7:28 am
[...] Using IContextChannel Extensions to Store Custom Data (Dan Rigsby) [...]