WCF KeepAliveEnabled to false for WS or Basic HTTP binding, What it supposed to do???

4 באוגוסט 2008

Hi All,


There is property called KeepAliveEnabled on HttpTransportBindingElement of WS\Basic http binding. This property can be change on the WCF client configuration only in custom binding. On WS\Basic http binding you can reach the KeepAliveEnabled property only using code.


Code Example:



ServiceHost host;



Type serviceType = typeof(MyService);


host = new ServiceHost(serviceType);


 


ServiceEndpointCollection endpoints = host.Description.Endpoints;


 


foreach (ServiceEndpoint endpoint in endpoints)


{


     if (endpoint.Name == "wsHttpEndPoint")


     {



           endpoint.Binding.CreateBindingElements().Find<HttpTransportBindingElement>().KeepAliveEnabled = false;


           break;


     }


}


 


The default behavior of WCF is to work with KeepAliveEnabled=true, so when WCF client proxy open connection and decide not to close it, the connection stay open because of the keep alive HTTP header (Connection=KeepAlive) that server forward to client.


if I want to change the default behavior and force the client proxy to be closed on each call, even if client did not call to proxy.close on its code. What do we have to do???


 


I thought that by changing the KeepAliveEnabled to false on the WCF service I can reach this goal. Unfortunately I was worng by changing this property to false nothing happned and the proxy still act the same.


Can someone explain what is this KeepAliveEnabled behavior means and how to use it? Is it works only on the WCF client side configuration?


 


Well probably the answer is yes. This property works only on the client side configuration and it also make sense.


 


If you still want to control the keep alive on the server side you can do it with this simple trick.


For this trick I use: WCF Message Inspector.


Now lets see some code example:


 


Step 1 create HeaderMessageInspector.cs



namespace CoregistrationPostingWindowsService


{


    public class HeaderMessageInspector : IDispatchMessageInspector


    {


        #region IDispatchMessageInspector Members


 


        public void BeforeSendReply(ref Message reply, object correlationState)


        {


            HttpResponseMessageProperty httpResponseProperty = new HttpResponseMessageProperty();


            httpResponseProperty.Headers.Add(HttpRequestHeader.Connection, "close");


            reply.Properties[HttpResponseMessageProperty.Name] = httpResponseProperty;


        }


 


        public object AfterReceiveRequest(ref Message request, IClientChannel channel,


                                                            InstanceContext instanceContext)


        {


            return null;


        }


 


        #endregion


    }


}


 


Step 2 create HeaderEndpointBehavior.cs



namespace MyService


{


    public class HeaderEndpointBehavior : IEndpointBehavior


    {


        #region IEndpointBehavior Members


 


        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)


        {


        }


 


        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)


        {


            throw new Exception("Behavior not supported on the consumer side!");


        }


 


        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)


        {


            HeaderMessageInspector inspector = new HeaderMessageInspector();


            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);


        }


 


        public void Validate(ServiceEndpoint endpoint)


        {


        }


 


        #endregion


    }


}


 


Step 3 create HeaderBehaviorExtensionElement.cs



namespace MyService


{


    public class HeaderBehaviorExtensionElement : BehaviorExtensionElement


    {


        public override Type BehaviorType


        {


            get { return typeof(HeaderEndpointBehavior); }


        }


 


        protected override object CreateBehavior()


        {


            return new HeaderEndpointBehavior();


        }


    }


}


 


Step 4 Register the message inspector on our service


I will do it by code but you can do it also with configuration if you like.


 



ServiceHost host;



Type serviceType = typeof(MyService);


host = new ServiceHost(serviceType);


 


ServiceEndpointCollection endpoints = host.Description.Endpoints;


 


foreach (ServiceEndpoint endpoint in endpoints)


{


    if (endpoint.Name == "wsHttpEndPoint")


    {


        // Register the header endpoint with the message inspector.


        endpoint.Behaviors.Add(new HeaderEndpointBehavior());


        break;


    }


}


 


host.Open();


 


 


After the message inspector registration we can now add to each Web Service call on the function:


public void BeforeSendReply(ref Message reply, object correlationState) 


The custom HTTP header that will be send to client. We add the header Connection=close. This HTTP header mark to client to close connection immediately after the call, so even if the user forget to call to proxy.close() on its code the connection will be close automatically.


 


Well I really want to here your comments on this issue.


Bye Rotem.


 

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

2 comments

  1. Ricardo14 בינואר 2010 ב 16:08

    Is this not the same as disabling keep alive on the site in IIS. I ran a quick test using tcpTrace with keep-alive disabled in IIS and all the responses were returned with Connection: close in the HTTP header.

    When I enabled keep alive again in IIS this was no longer the case.

    Reply
  2. Greg Hoover3 באפריל 2010 ב 7:33

    The reason

    endpoint.Binding.CreateBindingElements().
    Find().
    KeepAliveEnabled = false;
    break;

    did not work is because CreateBindingElements returns a clone of the binding elements and not the actual binging elements.

    Need to use a CustomBinding to get the values to "stick":
    http://www.sajay.com/post/2010/01/29/How-to-create-a-custom-binding-from-a-StandardBinding.aspx

    Reply