none
BeforeSendRequest question

    Question

  • Hi Everyone -

    I am trying to perform some modifications to the message in the BeforeSendRequest event.  What would be good is if I could just load the message into an XmlDocument, perform the changes that I need, and then update the message that is passed in by ref.

    I can load the XmlDocument; however, I don't see a clear way to use to get that to update the message reference that is passed into the method.

    Is this possible?  Is there a better way to do this?

    Thanks.
    Ken

    Monday, June 22, 2009 4:19 PM

Answers

  • You can definitely do that, just open the XmlDocument as a reader, and create a new message from it. The example below shows how this can be done:

        public class Post_f01a7120_0351_4be2_b45f_b7fb382c8a1f
        {
            [ServiceContract]
            public interface ITest
            {
                [OperationContract]
                string Echo(string input);
            }
            [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
            public class Service : ITest
            {
                public string Echo(string input)
                {
                    return input;
                }
            }
            public class MyInspector : IDispatchMessageInspector, IEndpointBehavior
            {
                public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
                {
                    return null;
                }
                public void BeforeSendReply(ref Message reply, object correlationState)
                {
                    MemoryStream ms = new MemoryStream();
                    XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(ms);
                    reply.WriteMessage(writer);
                    writer.Flush();
                    ms.Position = 0;
                    XmlDocument doc = new XmlDocument();
                    doc.Load(ms);
    
                    // change XmlDocument
                    XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
                    nsManager.AddNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/");
                    nsManager.AddNamespace("tempuri", "http://tempuri.org/");
                    XmlNode node = doc.SelectSingleNode("/s:Envelope/s:Body/tempuri:EchoResponse/tempuri:EchoResult", nsManager);
                    if (node != null)
                    {
                        node.InnerText = node.InnerText + " - modified";
                    }
    
                    ms = new MemoryStream();
                    writer = XmlDictionaryWriter.CreateTextWriter(ms);
                    doc.WriteTo(writer);
                    writer.Flush();
                    ms.Position = 0;
                    XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(ms, XmlDictionaryReaderQuotas.Max);
                    Message newReply = Message.CreateMessage(reader, int.MaxValue, reply.Version);
                    reply = newReply;
                }
                public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
    
                public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { }
    
                public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
                {
                    endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
                }
                public void Validate(ServiceEndpoint endpoint) { }
            }
            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), new BasicHttpBinding(), "");
                endpoint.Behaviors.Add(new MyInspector());
                host.Open();
                Console.WriteLine("Host opened");
    
                ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
                ITest proxy = factory.CreateChannel();
                Console.WriteLine(proxy.Echo("Hello world"));
                ((IClientChannel)proxy).Close();
                factory.Close();
    
                Console.WriteLine("Press ENTER to close");
                Console.ReadLine();
                host.Close();
            }
        }
    
    • Marked as answer by kennj Tuesday, June 23, 2009 12:36 AM
    Monday, June 22, 2009 6:51 PM

All replies

  • You can definitely do that, just open the XmlDocument as a reader, and create a new message from it. The example below shows how this can be done:

        public class Post_f01a7120_0351_4be2_b45f_b7fb382c8a1f
        {
            [ServiceContract]
            public interface ITest
            {
                [OperationContract]
                string Echo(string input);
            }
            [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
            public class Service : ITest
            {
                public string Echo(string input)
                {
                    return input;
                }
            }
            public class MyInspector : IDispatchMessageInspector, IEndpointBehavior
            {
                public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
                {
                    return null;
                }
                public void BeforeSendReply(ref Message reply, object correlationState)
                {
                    MemoryStream ms = new MemoryStream();
                    XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(ms);
                    reply.WriteMessage(writer);
                    writer.Flush();
                    ms.Position = 0;
                    XmlDocument doc = new XmlDocument();
                    doc.Load(ms);
    
                    // change XmlDocument
                    XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
                    nsManager.AddNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/");
                    nsManager.AddNamespace("tempuri", "http://tempuri.org/");
                    XmlNode node = doc.SelectSingleNode("/s:Envelope/s:Body/tempuri:EchoResponse/tempuri:EchoResult", nsManager);
                    if (node != null)
                    {
                        node.InnerText = node.InnerText + " - modified";
                    }
    
                    ms = new MemoryStream();
                    writer = XmlDictionaryWriter.CreateTextWriter(ms);
                    doc.WriteTo(writer);
                    writer.Flush();
                    ms.Position = 0;
                    XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(ms, XmlDictionaryReaderQuotas.Max);
                    Message newReply = Message.CreateMessage(reader, int.MaxValue, reply.Version);
                    reply = newReply;
                }
                public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
    
                public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { }
    
                public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
                {
                    endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
                }
                public void Validate(ServiceEndpoint endpoint) { }
            }
            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), new BasicHttpBinding(), "");
                endpoint.Behaviors.Add(new MyInspector());
                host.Open();
                Console.WriteLine("Host opened");
    
                ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
                ITest proxy = factory.CreateChannel();
                Console.WriteLine(proxy.Echo("Hello world"));
                ((IClientChannel)proxy).Close();
                factory.Close();
    
                Console.WriteLine("Press ENTER to close");
                Console.ReadLine();
                host.Close();
            }
        }
    
    • Marked as answer by kennj Tuesday, June 23, 2009 12:36 AM
    Monday, June 22, 2009 6:51 PM
  • That is exactly what I needed.  Thanks!
    Tuesday, June 23, 2009 12:36 AM
  • I am trying to do the same thing with the IClientMessageInspector.  I have looked around online and found examples but I can't seem to get this down.  I also need to add message level security through .NET code.  The service requires that I provide UserNameToken credentials.  I have been working on this for about 3-4 days now and I am running out of time.  Any help would be greatly appreciated.
    Tuesday, October 18, 2011 2:24 PM