none
Modifying request.Headers.MessageId in IClientMessageInspector.BeforeSendRequest

    Question



  • *** I implement a ClientMessageInspector, and have added the MessageId field as below.

    public class ClientMessageInspector : IEndpointBehavior, IClientMessageInspector
    {
        public string RequestMessage { get; set; }
        public string ResponseMessage { get; set; }
        public UniqueId MessageId { get; set; }
       
    *** In BeforeSendRequest I added this statement - request.Headers.MessageId = this.MessageId; , as below.
       
    object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
    {
        this.RequestMessage = request.ToString();
        request.Headers.MessageId = this.MessageId;   
       
       
    *** When setting a breakpoint after  request.Headers.MessageId = this.MessageId; in BeforeSendRequest,
    *** I can see that the new MessageId is assigned.
    *** When I inspect the outgoing SOAP Envelope , however, it contains a different value in the MessageId Header.
    *** What am I missing or doing incorrectly here?

        this._MessageID = new UniqueId();
        ClientMessageInspector inspector = new ClientMessageInspector();
        MyClient client = new MyClient("My");
        client.Endpoint.Behaviors.Add(inspector);
        inspector.MessageId = this._MessageID;

        EndpointAddress epa = new EndpointAddress(client.Endpoint.Address.Uri.ToString());
        ChannelFactory<MyChannel> factory = new ChannelFactory<MyChannel>(client.Endpoint);
        MyChannel MyChannel = factory.CreateChannel();

        OperationContextScope contextScope = new OperationContextScope(MyChannel);

        CustomHeader hdr = new CustomHeader(this._SomeValue, "ABC");

        OperationContext.Current.OutgoingMessageHeaders.Add(hdr);

        Response response = MyChannel.request(param);
    Wednesday, March 09, 2011 6:45 PM

Answers

  • On the code you posted originally, you first save the request message string into inspector.RequestMessage, and only after it you set the MessageId. If you save the request message after setting the MessageId header, do you get the expected value for it?

    And yes, the VSDebuggger... stuff is added by VS.

    • Marked as answer by oldevel Friday, March 11, 2011 11:35 AM
    Thursday, March 10, 2011 5:06 PM

All replies

  • That should just work (the example below is similar to your code). Where do you see on the outgoing message that the message id wasn't modified? Do you see it on the wire?

      public class Post_9fc5c26f_e2ee_410f_8490_a046e6d35770
      {
        [ServiceContract]
        public interface ITest
        {
          [OperationContract]
          string Echo(string text);
        }
        public class Service : ITest
        {
          public string Echo(string text)
          {
            return OperationContext.Current.IncomingMessageHeaders.MessageId.ToString();
          }
        }
        class ClientMessageInspector : IEndpointBehavior, IClientMessageInspector
        {
          public string RequestMessage { get; set; }
          public string ResponseMessage { get; set; }
          public UniqueId MessageId { get; set; }
    
          public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
          {
          }
    
          public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
          {
            clientRuntime.MessageInspectors.Add(this);
          }
    
          public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
          {
          }
    
          public void Validate(ServiceEndpoint endpoint)
          {
          }
    
          public void AfterReceiveReply(ref Message reply, object correlationState)
          {
            this.ResponseMessage = reply.ToString();
          }
    
          public object BeforeSendRequest(ref Message request, IClientChannel channel)
          {
            request.Headers.MessageId = this.MessageId;
            this.RequestMessage = request.ToString();
    
            return null;
          }
        }
        static Binding GetBinding()
        {
          return new WSHttpBinding(SecurityMode.None);
        }
        class MyClient : ClientBase<ITest>, ITest
        {
          public MyClient(Binding binding, EndpointAddress endpointAddress)
            : base(binding, endpointAddress)
          {
          }
    
          public string Echo(string text)
          {
            return this.Channel.Echo(text);
          }
        }
        public static void Test()
        {
          string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
          ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
          ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), GetBinding(), "");
          host.Open();
          Console.WriteLine("Host opened");
    
          ClientMessageInspector inspector1 = new ClientMessageInspector();
          byte[] id = new byte[16]; for (int i = 0; i < id.Length; i++) id[i] = (byte)1;
          inspector1.MessageId = new UniqueId(id);
          MyClient client = new MyClient(GetBinding(), new EndpointAddress(baseAddress));
          client.Endpoint.Behaviors.Add(inspector1);
    
          ChannelFactory<ITest> factory1 = new ChannelFactory<ITest>(client.Endpoint);
          ITest proxy1 = factory1.CreateChannel();
          using (new OperationContextScope((IContextChannel)proxy1))
          {
            OperationContext.Current.OutgoingMessageHeaders.Add(MessageHeader.CreateHeader("name", "ns", "value"));
            Console.WriteLine(proxy1.Echo("foo"));
          }
    
          Console.WriteLine(inspector1.RequestMessage);
          Console.WriteLine(inspector1.ResponseMessage);
    
          Console.Write("Press ENTER to close the host");
          Console.ReadLine();
          host.Close();
        }
      }
    
    
    Wednesday, March 09, 2011 8:11 PM
  • Carlos, thank you very much for your response, and the sample code.

    In my code, both in the success and Exception paths of the code, after  Response response = myChannel.request(param); , I record both the request and response messages as follows:

    string req = inspector.RequestMessage;
    string resp = inspector.ResponseMessage;

    When I inspect the outgoing SOAP Envelope using Fiddler, my injected MessageId is present, together with the following header elements. I trust the <VsDebuggerCausalityData.. element has to do with Visual Studio, and the rest are added in from app.config  after IClientMessageInspector.BeforeSendRequest .

    <VsDebuggerCausalityData ...
    <a:To s:mustUnderstand="1...
    <wsse:Security s:mustUnderstand="1...
    <wsse:UsernameToken>...
      <wsse:Username>...
      <wsse:Password Type="...
    </wsse:UsernameToken>...
    </wsse:Security>

    When I look at the recorded inspector.RequestMessage, I see a different MessageId, the above elements are not present, and the rest of the SOAP message is the same.

    Could you perhaps shed any light on why this could be the case?

     

    I am somewhat new to WCF and have not yet written a service. My attempt to implement your example fails on host.Open(); with the following: HTTP could not register URL http://+:8000/Service/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details).

    I successfully executed the following statement, but I still get the failure on host.Open(); , so I suspect I'm missing something in a config file, or some additional steps.

    netsh http add urlacl http://localhost:8000/Service user=Ol

    Many thanks

    Ol

    Thursday, March 10, 2011 7:37 AM
  • On the code you posted originally, you first save the request message string into inspector.RequestMessage, and only after it you set the MessageId. If you save the request message after setting the MessageId header, do you get the expected value for it?

    And yes, the VSDebuggger... stuff is added by VS.

    • Marked as answer by oldevel Friday, March 11, 2011 11:35 AM
    Thursday, March 10, 2011 5:06 PM
  • Carlos, thanks for pointing that out. Simple oversight on my part. It's sorted.
    Friday, March 11, 2011 11:35 AM