20100315

WCF Session

You may need to define object that behaves like HttpSession and bind it to the WCF request. It's pretty useful when you want to keep Fluent NHibernate session opened during WCF call.

First define the Endpoint Extension that will hold the session state.

public class ExampleEndpointExtension : IExtension
    {
        public ExampleEndpointExtension()
        {
            State = new Dictionary();
        }

        public IDictionary State { get; private set; }

        public void Attach(OperationContext owner) { }
        public void Detach(OperationContext owner) { }
    }

Then you need to bind it to the Call Context.

public class ExampleEndpointContextInitializer : ICallContextInitializer
    {
        public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
        {
            bool found = false;
            foreach (IExtension extension in OperationContext.Current.Extensions)
            {
                if (extension is ExampleEndpointExtension)
                {
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                OperationContext.Current.Extensions.Add(new ExampleEndpointExtension());
            }
            return new object();
        }

        public void AfterInvoke(object correlationState)
        {            
        }
    }

Last class to implement is Endpoint Behaviour Extension.

public class ExampleEndpointBehavior : BehaviorExtensionElement,IEndpointBehavior
    {

        public override Type BehaviorType
        {
            get { return typeof(ExampleEndpointBehavior); }
        }

        protected override object CreateBehavior()
        {
            return new ExampleEndpointBehavior();
        }

        public void Validate(ServiceEndpoint endpoint)
        {            
        }

        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {            
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
            EndpointDispatcher endpointDispatcher)
        {
            foreach (DispatchOperation operation in endpointDispatcher.DispatchRuntime.Operations)
            {
                operation.CallContextInitializers.Add(new ExampleEndpointContextInitializer());
            }
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {            
        }
    }

You should add your extension in web.config (or app.config).
Remember to define assembly together with version and culture. There's a bug in framework that will cause load fail if you omit it.
<behaviorextensions>
    <add name="ExampleBehaviorExtension" type="Example.Session.ExampleEndpointBehavior, Example, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>

Now you can use it:

foreach (IExtension extension in OperationContext.Current.Extensions)
{
    if (extension is ExampleEndpointExtension)
    {
        ((ExampleEndpointExtension)extension).State["SESSION_ITEM"] = "test";
    }
}

Example of usage in next post Binding Fluent NHibernate session to WCF call.

No comments: