Search code examples
c#wcfsoapnamespacesclient

How can I add a namespace to soap envelope in c#


I want to add a namespace setting to my soap envelope. I would like to change it in the BeforeSendRequest in an IClientMessageInspector or you have a more elegant way.

For example

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
 <s:Header>
  <wsa:To xmlns="http://www.w3.org/2005/08/addressing">ws://xxx/V1</wsa:To>
  ...
 </s:Header>
 <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  ...
 </s:Body>
</s:Envelope>

to

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing">
...

please help me!

Thank you!


Solution

  • According to your description, I think you could use WCF Message Inspector. Before the client send the message. We could customize the message body.
    https://learn.microsoft.com/en-us/dotnet/framework/wcf/samples/message-inspectors
    I have made a demo, wish it is useful to you.
    Server end.

    class Program
        {
    
            static void Main(string[] args)
            {
                Uri uri = new Uri("http://localhost:1500");
                BasicHttpBinding binding = new BasicHttpBinding();
                binding.TransferMode = TransferMode.Buffered;
                binding.Security.Mode = BasicHttpSecurityMode.None;
                ServiceHost sh = new ServiceHost(typeof(Calculator),uri);
                sh.AddServiceEndpoint(typeof(ICalculator), binding, "");
                ServiceMetadataBehavior smb;
                smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
                if (smb == null)
                {
                    smb = new ServiceMetadataBehavior();
                    //smb.HttpGetEnabled = true;
                    sh.Description.Behaviors.Add(smb);
                }
                Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
                sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "MEX");
    
    
                sh.Open();
                Console.Write("Service is ready....");
                Console.ReadLine();
                sh.Close();
            }
        }
        [ServiceContract]
        public interface ICalculator
        {
            [OperationContract,WebGet]
            double Add(double a, double b);
    
        }
    
        public class Calculator : ICalculator
        {
            public double Add(double a, double b)
            {
                return a + b;
            }
    
    }
    

    Client.

    class Program
        {
            static void Main(string[] args)
            {
                ServiceReference2.CalculatorClient client = new ServiceReference2.CalculatorClient();
                try
                {
                    var result = client.Add(34, 20);
                    Console.WriteLine(result);
                }
                catch (Exception)
                {
                    throw;
                }
            }
    
        }
        public class ClientMessageLogger : IClientMessageInspector
        {
            public void AfterReceiveReply(ref Message reply, object correlationState)
            {
                string result = $"server reply message:\n{reply}\n";
                Console.WriteLine(result);
            }
    
            public object BeforeSendRequest(ref Message request, IClientChannel channel)
            {
    
                XmlDocument doc = new XmlDocument();
                MemoryStream ms = new MemoryStream();
                XmlWriter writer = XmlWriter.Create(ms);
                request.WriteMessage(writer);
                writer.Flush();
                ms.Position = 0;
                doc.Load(ms);
    
                ChangeMessage(doc);
    
                ms.SetLength(0);
                writer = XmlWriter.Create(ms);
    
                doc.WriteTo(writer);
                writer.Flush();
                ms.Position = 0;
                XmlReader reader = XmlReader.Create(ms);
                request = System.ServiceModel.Channels.Message.CreateMessage(reader, int.MaxValue, request.Version);
                string result = $"client ready to send message:\n{request}\n";
                Console.WriteLine(result);
                return null;
            }
            void ChangeMessage(XmlDocument doc)
            {
                XmlElement element = (XmlElement)doc.GetElementsByTagName("s:Envelope").Item(0);
                if (element != null)
                {
                    element.SetAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
                    element.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
                }
            }
        }
        public class CustContractBehaviorAttribute : Attribute, IContractBehavior, IContractBehaviorAttribute
        {
            public Type TargetContract => typeof(ICalculator);
    
            public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
            {
                return;
            }
    
            public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
                clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
            }
    
            public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
            {
                return;
            }
    
            public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
            {
                return;
            }
    }  
    

    Don’t forget apply the CustContractbehavior to the service interface.

        [CustContractBehavior]
    public interface ICalculator {
    

    Result. enter image description here