none
Add and retrieve parameters in headers to WCF calls RRS feed

  • Question

  • I hope this is the right foum for my WCF question.

    I need to pass 2 extra parameters with each WCF call. I have included the source code of a super-simple service and client, with everything in code, not in the config. (I have a number of reasons to keep it that way) In my sample I use a self-hosted service in a console app and a client console app.

    What do I need to change in the code to enable passing parameters (shall we call them hidden parameters) in the WCF heading? The following code actually works. Of course I am not actually passing UserName and ClientNo in the Header, but I would like to be able to. I believe I read somewhere that this could be accomplished in how I set up the binding. I would like to know how to do it by modifying this sample code, rather than bringing in some massive library. Thanks.

    //=============== the service
    using System;
    using System.Collections.Generic;
    using GreetingService;
    using System.ServiceModel;
    using System.ServiceModel.Description;

    namespace GreetingServiceHost
    {
        class Program
        {
            static void Main(string[] args)
            {
                string Port = "7799";
                string SvcName = "GreetingService";
                string Addr = "http://localhost:" + Port + "/" + SvcName;
                Uri AddrBase = new Uri(Addr);

                ServiceHost svchost = new ServiceHost(typeof(GreetingService.GreetingService), AddrBase);
                ServiceMetadataBehavior metaBehave = new ServiceMetadataBehavior();
                svchost.Description.Behaviors.Add(metaBehave);
                svchost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");

                BasicHttpBinding httpb = new BasicHttpBinding();
                SetBinding(httpb);

                svchost.AddServiceEndpoint(typeof(IGreetingService), httpb, Addr);

                svchost.Open();

                Console.WriteLine(Addr);
                Console.Write(SvcName);
                Console.WriteLine(" service is running. Press any key to close.");
                Console.ReadKey(true);
            }

            public static void SetBinding(BasicHttpBinding httpb)
            {
                httpb.Name = "bigbinding";
                httpb.CloseTimeout = new TimeSpan(0, 10, 0);
                httpb.OpenTimeout = new TimeSpan(0, 10, 0);
                httpb.ReceiveTimeout = new TimeSpan(0, 10, 0);
                httpb.AllowCookies = false;
                httpb.BypassProxyOnLocal = false;
                httpb.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
                httpb.MaxBufferPoolSize = 2000000;
                httpb.MaxBufferSize = 2000000;
                httpb.MaxReceivedMessageSize = 2000000;
                httpb.MessageEncoding = WSMessageEncoding.Text;
                httpb.TextEncoding = System.Text.Encoding.UTF8;
                httpb.TransferMode = TransferMode.Streamed;
                httpb.UseDefaultWebProxy = true;
               
                httpb.SendTimeout = new TimeSpan(0, 10, 0);

            }

        }//class

    }//program

    using System;
    using System.Collections.Generic;
    using System.ServiceModel;

    namespace GreetingService
    {
        [ServiceContract]
        public interface IGreetingService
        {
            [OperationContract]
            string Greet(string greeting);
        }//interface

    }//namespace

    using System;
    using System.Collections.Generic;

    namespace GreetingService
    {
        public class GreetingService : IGreetingService
        {
            // Simulate values retrieved from header
            string UserName = "jon_q_jacobs";
            int ClientNo = 23;

            public string Greet(string greeting)
            {
                return greeting + " " + UserName + ", of Client " + ClientNo.ToString();
            }

        }//class

    }//namespace

    //==================== the client

    using System;
    using System.Collections.Generic;

    namespace GreetingClient
    {
        class Program
        {
            static void Main(string[] args)
            {
                // Simulate values added to header
                string UserName = "jon_q_jacobs";
                int ClientNo = 23;

                GreetProxy GP = new GreetProxy();
                string answer = GP.greetingService.Greet("Hello");

                Console.WriteLine(answer);

                Console.ReadKey();
            }

        }//class

    }//namespace

    using System;
    using System.Collections.Generic;
    using System.ServiceModel;

    namespace GreetingClient
    {
        [ServiceContract]
        public interface IGreetingService
        {
            [OperationContract]
            string Greet(string greeting);
        }//interface

    }//namespace

    using System;
    using System.Collections.Generic;
    using System.ServiceModel;

    namespace GreetingClient
    {
        public class GreetProxy
        {
            /// <summary>
            /// The service's interface
            /// </summary>
            public IGreetingService greetingService;

            public GreetProxy()
            {
                string Server = "http://localhost";
                string GR_App = ":7799";
                string GR_Service = "/GreetingService";

                string EPAddr = Server + GR_App + GR_Service;
                EndpointAddress ep = new EndpointAddress(EPAddr);
                BasicHttpBinding httpb = new BasicHttpBinding();
                SetBinding(httpb);
                ChannelFactory<IGreetingService> channelFactory = new ChannelFactory<IGreetingService>(httpb);
                greetingService = channelFactory.CreateChannel(ep);
            }

            public void SetBinding(BasicHttpBinding httpb)
            {
                httpb.Name = "bigbinding";
                httpb.CloseTimeout = new TimeSpan(0, 10, 0);
                httpb.OpenTimeout = new TimeSpan(0, 10, 0);
                httpb.ReceiveTimeout = new TimeSpan(0, 10, 0);
                httpb.AllowCookies = false;
                httpb.BypassProxyOnLocal = false;
                httpb.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
                httpb.MaxBufferPoolSize = 2000000;
                httpb.MaxBufferSize = 2000000;
                httpb.MaxReceivedMessageSize = 2000000;
                httpb.MessageEncoding = WSMessageEncoding.Text;
                httpb.TextEncoding = System.Text.Encoding.UTF8;
                httpb.TransferMode = TransferMode.Streamed;
                httpb.UseDefaultWebProxy = true;
                httpb.ReaderQuotas.MaxDepth = 32;
                httpb.ReaderQuotas.MaxStringContentLength = 2000000;
                httpb.ReaderQuotas.MaxArrayLength = 2000000;
                httpb.ReaderQuotas.MaxBytesPerRead = 4096;
                httpb.ReaderQuotas.MaxNameTableCharCount = 2000000;
            }

        }//class

    }//namespace

    Although these programs are about as minimalist as possible, it is still a lot to read in a forum posting, so I really appreciate anyone's attempt to help. Jon Jacobs


    Jon Jacobs&lt;br/&gt; Not sent from my iPhone, because I don't have one.

    Tuesday, March 29, 2016 7:21 PM

Answers

  • Hello,

    In WCF if we want to add the custom message header during the communication, one way is that we can use the Message Inspectors .

    Firstly, you need to create a custom class that is inherited the IClientMessageInspector IDispatchMessageInspector and implement the method named BeforeSendRequest (add parameter inside the header) and AfterReceiveRequest(retrieve header parameter) as following:

    public class MessageIntercept : IClientMessageInspector, IDispatchMessageInspector
        {
            public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
            {
               // add header message
                System.ServiceModel.Channels.MessageHeader hdUserName = System.ServiceModel.Channels.MessageHeader.CreateHeader("username", "myTest", "admin");
                System.ServiceModel.Channels.MessageHeader hdPassWord = System.ServiceModel.Channels.MessageHeader.CreateHeader("clientno", "myTest", "123");
                request.Headers.Add(hdUserName);
                request.Headers.Add(hdPassWord);
                return null;
            }
           public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
            {
                // (Service) retieve header message  
                string username = request.Headers.GetHeader<string>("username", "myTest");
                string clientno = request.Headers.GetHeader<string>("clientno", "myTest");
                return null;
            }
    }


    Secondly, you need to add a custom class that is inherited from IEndpointBehavior as following:

    public class MyEndPointBehavior : IEndpointBehavior {
    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { //client clientRuntime.ClientMessageInspectors.Add(new MessageIntercept()); } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { //service endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MessageIntercept()); } }

    Thirdly, you need to add the custom EndpointBehavior to your client code.

    YourGreetProxy YGP = new YourGreetProxy();
    YGP.Endpoint.EndpointBehaviors.Add(new MyEndPointBehavior());

    And adding the following code snippet to your service code:

    ServiceHost svchost = new ServiceHost(typeof(Service.GreetingService), AddrBase);
    foreach (var endPoint in svchost.Description.Endpoints)
                {
                    endPoint.EndpointBehaviors.Add(new MyEndPointBehavior());
                }


    For more information, please refer to:
    https://blogs.msdn.microsoft.com/carlosfigueira/2011/04/18/wcf-extensibility-message-inspectors/ .

    Best Regards,
    Amy Peng


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.



    Wednesday, March 30, 2016 4:51 AM
    Moderator

All replies

  • Hello,

    In WCF if we want to add the custom message header during the communication, one way is that we can use the Message Inspectors .

    Firstly, you need to create a custom class that is inherited the IClientMessageInspector IDispatchMessageInspector and implement the method named BeforeSendRequest (add parameter inside the header) and AfterReceiveRequest(retrieve header parameter) as following:

    public class MessageIntercept : IClientMessageInspector, IDispatchMessageInspector
        {
            public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
            {
               // add header message
                System.ServiceModel.Channels.MessageHeader hdUserName = System.ServiceModel.Channels.MessageHeader.CreateHeader("username", "myTest", "admin");
                System.ServiceModel.Channels.MessageHeader hdPassWord = System.ServiceModel.Channels.MessageHeader.CreateHeader("clientno", "myTest", "123");
                request.Headers.Add(hdUserName);
                request.Headers.Add(hdPassWord);
                return null;
            }
           public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
            {
                // (Service) retieve header message  
                string username = request.Headers.GetHeader<string>("username", "myTest");
                string clientno = request.Headers.GetHeader<string>("clientno", "myTest");
                return null;
            }
    }


    Secondly, you need to add a custom class that is inherited from IEndpointBehavior as following:

    public class MyEndPointBehavior : IEndpointBehavior {
    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { //client clientRuntime.ClientMessageInspectors.Add(new MessageIntercept()); } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { //service endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MessageIntercept()); } }

    Thirdly, you need to add the custom EndpointBehavior to your client code.

    YourGreetProxy YGP = new YourGreetProxy();
    YGP.Endpoint.EndpointBehaviors.Add(new MyEndPointBehavior());

    And adding the following code snippet to your service code:

    ServiceHost svchost = new ServiceHost(typeof(Service.GreetingService), AddrBase);
    foreach (var endPoint in svchost.Description.Endpoints)
                {
                    endPoint.EndpointBehaviors.Add(new MyEndPointBehavior());
                }


    For more information, please refer to:
    https://blogs.msdn.microsoft.com/carlosfigueira/2011/04/18/wcf-extensibility-message-inspectors/ .

    Best Regards,
    Amy Peng


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.



    Wednesday, March 30, 2016 4:51 AM
    Moderator
  • Thank you very much.

    >GreetProxy GP = new GreetProxy();
    >GP
    .Endpoint.EndpointBehaviors.Add(new MyEndPointBehavior());

    My public class GreetProxy

    is a very simple class, and it does not have an Endpoint property. Is there some interface should it implement to have this property?

    Thanks again,


    Jon Jacobs&lt;br/&gt; Not sent from my iPhone, because I don't have one.

    Wednesday, March 30, 2016 8:48 PM
  • I found a way:

    GP.channelFactory.Endpoint.Behaviors.Add(new

    BTW, I do not see Endpoint.EndpointBehaviors. I only see Endpoint.Behaviors

    Jon Jacobs&lt;br/&gt; Not sent from my iPhone, because I don't have one.

    Thursday, March 31, 2016 4:48 PM
  • I finally got it to work. Whew!!!

    Thank you very much.


    Jon Jacobs&lt;br/&gt; Not sent from my iPhone, because I don't have one.

    Thursday, March 31, 2016 7:41 PM