title: WCF client, XML namespace prefix results in null object
body: <p>I have created a WCF service (.NET 4.6.2) and a third party has created the client. </p>
  
  <p>I have no control over the client, or the ability to get the third party to change anything, so any changes are going to be on the server side only.</p>
  
  <p>I have minimised and anonymised the code to the bare minimum to hopefully demonstrate the problem in as little code as possible. If I made any mistakes or you need any further detail, I will alter the details accordingly. </p>
  
  <p><br></p>
  
  <p><strong>Summary</strong></p>
  
  <p>The client is able to call the service, and the parser is able to correctly identify the method in code from the SOAP Action, however any objects passed in are always null. I am able to catch the requests with a breakpoint and see that the objects are null at runtime.</p>
  
  <p>I have identified that the problem is being caused mostly my an XML namespace prefix that the client is passing.</p>
  
  <p>I am able to intercept the incoming raw messages and I can see exactly what the client is sending. </p>
  
  <p>I am able to manipulate these incoming messages, for experimentation, and then post the modified version of the message to the service to test the results using a generic browser based client.</p>
  
  <p><br></p>
  
  <p><strong>Example Data Contract:-</strong></p>
  
  <pre><code>[DataContract(Namespace = "http://mycompanyname.co.uk")]
  public class SomeObject
  {
      [DataMember]
      public string SomeField { get; set; }
  }
  </code></pre>
  
  <p><br></p>
  
  <p><strong>Example Service Contract:-</strong></p>
  
  <pre><code>[ServiceContract(Namespace = "http://mycompanyname.co.uk")]
  public interface IIncoming
  {
      [OperationContract]
      XmlElement MyAction(SomeObject someObject);
  }
  </code></pre>
  
  <p><br></p>
  
  <p><strong>Example WCF service implementing the previously defined Service Contract:-</strong></p>
  
  <pre><code>[ServiceBehavior(Namespace = "http://mycompanyname.co.uk")]
  public class Incoming : IIncoming
  {
      public XmlElement MyAction(SomeObject someObject)
      {
          XmlDocument response = new XmlDocument();
          response.LoadXml("&lt;Response&gt;OK&lt;/Response&gt;");
          return response.DocumentElement;
      }
  }
  </code></pre>
  
  <p><br></p>
  
  <p><strong>This is what the 3rd party posts to the service:-</strong></p>
  
  <pre><code>/*3rd party original*/
  &lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"&gt;
      &lt;soapenv:Body&gt;
          &lt;ns1:MyAction xmlns:ns1="http://mycompanyname.co.uk"&gt;
              &lt;someObject xmlns=""&gt;
                  &lt;SomeField&gt;Blah&lt;/SomeField&gt;
              &lt;/someObject&gt;
          &lt;/ns1:MyAction&gt;
      &lt;/soapenv:Body&gt;
  &lt;/soapenv:Envelope&gt;
  </code></pre>
  
  <p>Breakpointing the code, I can see that the above results in MyAction being called, but MyObject is null</p>
  
  <p><br></p>
  
  <p>I modified the SOAP message to remove the blank xmlns, but someObject is still null</p>
  
  <pre><code>/*blank xmlns removed*/
  &lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"&gt;
      &lt;soapenv:Body&gt;
          &lt;ns1:MyAction xmlns:ns1="http://mycompanyname.co.uk"&gt;
              &lt;someObject&gt;
                  &lt;SomeField&gt;Blah&lt;/SomeField&gt;
              &lt;/someObject&gt;
          &lt;/ns1:MyAction&gt;
      &lt;/soapenv:Body&gt;
  &lt;/soapenv:Envelope&gt;
  </code></pre>
  
  <p><br></p>
  
  <p>I modified the SOAP message to remove the ns1 prefix, but someObject is still null</p>
  
  <pre><code>/*ns1 removed*/
  &lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"&gt;
      &lt;soapenv:Body&gt;
          &lt;MyAction xmlns="http://mycompanyname.co.uk"&gt;
              &lt;someObject xmlns=""&gt;
                  &lt;SomeField&gt;Blah&lt;/SomeField&gt;
              &lt;/someObject&gt;
          &lt;/MyAction&gt;
      &lt;/soapenv:Body&gt;
  &lt;/soapenv:Envelope&gt;
  </code></pre>
  
  <p><br></p>
  
  <p>Now if I both remove the ns1 prefix AND the blank xmlns, then someObject is correctly populated as expected. This resolves everything. The only problem is, I can't get the client to make this change.</p>
  
  <pre><code>/*both removed - works*/
  &lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"&gt;
      &lt;soapenv:Body&gt;
          &lt;MyAction xmlns="http://mycompanyname.co.uk"&gt;
              &lt;someObject&gt;
                  &lt;SomeField&gt;Blah&lt;/SomeField&gt;
              &lt;/someObject&gt;
          &lt;/MyAction&gt;
      &lt;/soapenv:Body&gt;
  &lt;/soapenv:Envelope&gt;
  </code></pre>
  
  <p><br></p>
  
  <p>So firstly, why does this happen? as I understand it in XML, the prefix is effectively irrelevant in determining an object, so <code>&lt;ns1:Something&gt;</code> should be the same object as <code>&lt;ns2:Something&gt;</code> or <code>&lt;Something&gt;</code>
  The WCF parser is however determining that <code>&lt;ns1:Something&gt;</code> is not a <code>&lt;Something&gt;</code></p>
  
  <p><br></p>
  
  <p>How can I resolve this problem server side, preferably from within the WCF service? I was thinking if there is a way to capture the message before it is parsed in the WCF service and strip the ns1: and blank xmlns out beforehand?</p>
  
  <p>Many thanks</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>Here is an example that you can copy/paste to reproduce the problem exactly:-</p>
  
  <p>Create a WCF Service Application (.NET Framework 4.6.2)</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Runtime.Serialization;
  using System.ServiceModel;
  using System.Text;
  using System.Xml;
  
  namespace GenericIncoming
  {
      [ServiceContract(Namespace = "http://mycompanyname.co.uk")]
      public interface IIncoming
      {
          [OperationContract]
          XmlElement MyAction(SomeObject someObject);
      }
  
      [DataContract(Namespace ="")]
      public class SomeObject
      {
          [DataMember]
          public string SomeField { get; set; }
      }
  }
  
  
  
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Runtime.Serialization;
  using System.ServiceModel;
  using System.Text;
  using System.Xml;
  
  namespace GenericIncoming
  {
      [ServiceBehavior(Namespace = "http://mycompanyname.co.uk")]
      public class Incoming : IIncoming
      {
          public XmlElement MyAction(SomeObject someObject)
          {
              XmlDocument response = new XmlDocument();
              if (someObject != null)
              {
                  response.LoadXml("&lt;Response&gt;OK&lt;/Response&gt;");
              }
              else
              {
                  response.LoadXml("&lt;Response&gt;NULL&lt;/Response&gt;");
              }
              return response.DocumentElement;
          }
      }
  }
  </code></pre>
  
  <p>Run your WCF service and POST this message to the service, and you will get an "OK" response</p>
  
  <pre><code>&lt;s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"&gt;
      &lt;s:Body&gt;
          &lt;MyAction xmlns="http://mycompanyname.co.uk"&gt;
              &lt;someObject&gt;
                  &lt;SomeField&gt;Blah&lt;/SomeField&gt;
              &lt;/someObject&gt;
          &lt;/MyAction&gt;
      &lt;/s:Body&gt;
  &lt;/s:Envelope&gt;
  </code></pre>
  
  <p>Now if you add the ns1 prefix, just like the 3rd party sends to me, then the response is "NULL" this means that the object in the WCF is null because the parser was unable to deal with the XML</p>
  
  <pre><code>&lt;s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"&gt;
      &lt;s:Body&gt;
          &lt;ns1:MyAction xmlns:ns1="http://mycompanyname.co.uk"&gt;
              &lt;someObject&gt;
                  &lt;SomeField&gt;Blah&lt;/SomeField&gt;
              &lt;/someObject&gt;
          &lt;/ns1:MyAction&gt;
      &lt;/s:Body&gt;
  &lt;/s:Envelope&gt;
  </code></pre>
  
  <p>This is the first problem that I am unable to resolve</p>