Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope


:P
On this page:

I've been working on a WCF client implementation that is calling into a rather peculiar service that is unable to handle messages sent from a WCF SOAP client. In particular the service I needed to call does not allow inline namespaces in the SOAP message and requires that all namespaces are declared with prefixes and declared on the SOAP:Envelope element. WCF by default doesn't work that way.

It felt like I entered into the real bizarro world of a service that was refusing valid XML messages because the messages were formatted a certain way. Specifically the service refuses to read inline namespace declaration and expects all the namespaces to be declared up front on the SOAP envelope. Yeah, you heard that right – send valid XML with validating namespace definitions, but which happen to be defined inline of the body rather than at the top of the envelope and the service fails with a hard exception on the backend.

Hmmm alrighty then… After a lot of back and forth with the provider it comes out that, yes "that's a known issue" and it will be fixed – sometime in the future to which I mentally added "presumably in the next 10 years". Not bloody likely that they are going to help me on the server side.

So since I wasn't going to get any help from the provider, I did what any good developer would do – search StackOverflow and the Web for a solution. Apparently this is not the most bizarre thing ever, as I assumed. A lot of Java/IBM based service apparently have this problem, but even so WCF solutions for this seem to be scarce. I even posted my own StackOverflow question, which I eventually answered myself with what I'm describing here in more detail.

Defining the Problem

To demonstrate what I'm talking about,here's a simple request that WCF natively creates when calling the service:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:Security>...</h:Security>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <cancelShipmentRequest xmlns="http://www.royalmailgroup.com/api/ship/V2">
      <integrationHeader>
        <dateTime xmlns="http://www.royalmailgroup.com/integration/core/V1">2016-04-02T01:39:06.1735839Z</dateTime>
        <version xmlns="http://www.royalmailgroup.com/integration/core/V1">2</version>
        <identification xmlns="http://www.royalmailgroup.com/integration/core/V1">
          <applicationId>RMG-API-G-01</applicationId>
          <transactionId>vw7nj5jcmtkc</transactionId>
        </identification>
      </integrationHeader>
      <cancelShipments>
        <shipmentNumber>TTT001908905GB</shipmentNumber>
      </cancelShipments>
    </cancelShipmentRequest>
  </s:Body>
</s:Envelope>

This is pretty typical of WCF messages which include a bunch of inline and duplicated namespace declarations. Some of them inherit down (like on cancelShipmentRequest) and others are defined on the actual nodes and repeated (all of the v1 namespaces basically). I'm not quite sure why WCF creates such verbosity in its messages rather than defining namespaces at the top since it is a lot cleaner, but regardless, what's generated matches the schema requirements of the WSDL and in theory the XML sent should work just fine.

But - as pointed out, the provider does not accept inline namespace declarations in the body, so no matter what I tried the requests were getting kicked back with 500 errors from the server. As you might expect, it a look a lot of trial and error and head beating to figure out that the namespaces were the problem. After confirming with the provider this is indeed the problem, a known problem with no workaround, on the server side and it became clear that the only way to get the service to work is to fix it on the client in the WCF Proxy.

Customizing the XML Message using a MessageFormatter

After a lot of digging (and a comment on my StackOverflow question that referenced this blog post) the solution was to implement a custom MessageFormatter in WCF. MessageFormatters sit inside of the WCF pipeline and get fired after a document has been created but before the message has been processed. This gives a chance to hook into various creation events and modify the message as its being created. Essentially I need to hook into the Envelope element creation and then add the namespaces and when creating a subclassed message object there is a way to hook into the Envelope generation event and at that time it's possible to inject the namespaces. And it turns out that this approach works – the namespaces get generated at the Envelope level in the SOAP document.

Creating a custom Message Object with WCF

The key element that has to be modified to handle the Envelope XML creation is the Message object which includes a OnWriteStartElement() method that can be overridden and where the namespaces can be added. But as usually is the case with WCF to get your custom class hooked you have to create several additional classes to get the pipeline to fire your custom handlers.

Leave it to WCF to make this process an exercise in composition hell.  In order to customize the message, three classes are needed:

  • Message Class
  • ClientMessageFormatter Class
  • FormatMessageAttribute Class

You then attach the attribute to each of the Operations in the Service contract interface to get the formatting applied. Most of the code in these classes is just default implementations with a couple of small places where you actually override the default behavior. For the most part this is implement and interface and change the one method that you're interested in.

So here we go – I'll start with the lowest level class that has the implementation and work my way up the stack.

Message Class

First  is the message class implementation which has the actual code that adds the namespaces needed.

 public class RoyalMailCustomMessage : Message
    {
        private readonly Message message;

        public RoyalMailCustomMessage(Message message)
        {
            this.message = message;
        }
        public override MessageHeaders Headers
        {
            get { return this.message.Headers; }
        }
        public override MessageProperties Properties
        {
            get { return this.message.Properties; }
        }
        public override MessageVersion Version
        {
            get { return this.message.Version; }
        }

        protected override void OnWriteStartBody(XmlDictionaryWriter writer)
        {
            writer.WriteStartElement("Body", "http://schemas.xmlsoap.org/soap/envelope/");
        }
        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
        {
            this.message.WriteBodyContents(writer);
        }
        protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
        {
            writer.WriteStartElement("soapenv", "Envelope", "http://schemas.xmlsoap.org/soap/envelope/");
            writer.WriteAttributeString("xmlns", "oas", null, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
            writer.WriteAttributeString("xmlns", "v2", null, "http://www.royalmailgroup.com/api/ship/V2");
            writer.WriteAttributeString("xmlns", "v1", null, "http://www.royalmailgroup.com/integration/core/V1");
            writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
            writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");            
        }
    }

The key method is OnWriteStartEnvelope() which receives an XmlWriter that you can use to explicitly create the header element. As you can see I add all the namespaces I need in the header here.

Note that you may have to have multiple message classes if various methods use different namespaces. Lucky for me the service I'm dealing with has only a couple of namespaces that are used for all the service methods so a single overload was all we needed for the methods we called on the service.

ClientMessageFormatter

WCF has two kinds of MessageFormatters: ClientMessageFormatter used for client proxy requests and DispatchMessageFormatter which is used for generating server side messages. So if you need to create custom messages for services use a DispatchMessageFormatter which has slightly different overloads than the ones shown here.

Here's the implementation of the ClientMessageFormatter I used:This code basically overrides the SerializeRequest() method and serializes the new message object we created that includes the overridden namespace inclusions.

public class RoyalMailMessageFormatter : IClientMessageFormatter
{
    private readonly IClientMessageFormatter formatter;

    public RoyalMailMessageFormatter(IClientMessageFormatter formatter)
    {
        this.formatter = formatter;
    }

    public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
    {
        var message = this.formatter.SerializeRequest(messageVersion, parameters);
        return new RoyalMailCustomMessage(message);
    }

    public object DeserializeReply(Message message, object[] parameters)
    {
        return this.formatter.DeserializeReply(message, parameters);
    }
}

FormatMessageAttribute

Finally we also need an attribute to hook up the new formatter to the actual service, which is done by attaching an attribute to the Service Operation on the contract. First you implement the attribute to attach the Formatter.

[AttributeUsage(AttributeTargets.Method)]
public class RoyalMailFormatMessageAttribute : Attribute, IOperationBehavior
{
    public void AddBindingParameters(OperationDescription operationDescription,
        BindingParameterCollection bindingParameters)
    { }

    public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
    {
        var serializerBehavior = operationDescription.Behaviors.Find<XmlSerializerOperationBehavior>();

        if (clientOperation.Formatter == null)
            ((IOperationBehavior)serializerBehavior).ApplyClientBehavior(operationDescription, clientOperation);
          
        IClientMessageFormatter innerClientFormatter = clientOperation.Formatter;
        clientOperation.Formatter = new RoyalMailMessageFormatter(innerClientFormatter);
    }

    public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
    { }

    public void Validate(OperationDescription operationDescription) { }
}

Here I hook up the custom formatter to the operation.

Note that this service uses XmlSerializer messages and because of that I look for the XmlSerializerOperationBehavior to find the behavior. In other cases you may have to use DataContractSerializerBehavior so be sure to step through the code to see which serializer is registered for the service/operation. 

That's a lot of freaking ceremony for essentially 10 lines of code that actually do what we need it to do – but at the same time it's pretty amazing that you get that level of control to hook into the process at such a low level. WCF never fails to shock and awe at the same time :-)

Hooking up the Attribute to Service Operations

When all of the ceremony is done the last thing left to do is to attach the behaviors to the operation contracts. In my case I'm using a WCF generated proxy so I do this in the generated Reference.cs file in the ServiceReferences folder (with show all files enabled):

[System.ServiceModel.OperationContractAttribute(Action="cancelShipment", ReplyAction="*")]
[System.ServiceModel.FaultContractAttribute(typeof(MarvelPress.Workflow.Business.RoyalShippingApi.exceptionDetails), 
Action=
"cancelShipment", Name="exceptionDetails")] [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)] [System.ServiceModel.ServiceKnownTypeAttribute(typeof(contactMechanism))] [System.ServiceModel.ServiceKnownTypeAttribute(typeof(baseRequest))] [RoyalMailFormatMessage] cancelShipmentResponse1 cancelShipment(MarvelPress.Workflow.Business.RoyalShippingApi.cancelShipmentRequest1 request);

And that's it – I'm now able to run my cancelShipment call against the service and make the request go through.

The new output generated includes all the namespaces at the top of the document (except for the SoapHeader which is generated separately and apparently *can* contain embedded namespaces):

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:v1="http://www.royalmailgroup.com/integration/core/V1"
                  xmlns:v2="http://www.royalmailgroup.com/api/ship/V2" 
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <h:Security>
    </h:Security>
  </s:Header>
  <soapenv:Body>
    <v2:cancelShipmentRequest>
      <v2:integrationHeader>
        <v1:dateTime>2016-04-02T07:54:34.9402872Z</v1:dateTime>
        <v1:version>2</v1:version>
        <v1:identification>
          <v1:applicationId>RMG-API-G-01</v1:applicationId>
          <v1:transactionId>he3q6qmer3tv</v1:transactionId>
        </v1:identification>
      </v2:integrationHeader>
      <v2:cancelShipments>
        <v2:shipmentNumber>TTT001908905GB</v2:shipmentNumber>
      </v2:cancelShipments>
    </v2:cancelShipmentRequest>
  </soapenv:Body>
</soapenv:Envelope>

And that puts me back in business. Yay!

A generic [EnvelopeNamespaces] Operation Attribute

The implementation above is specific to the service I was connecting to, but I figured it would be nice to make this actually a bit more generic, by letting you configure the namespaces you want to provide for each method. This will make it easier to work with service that might have different namespace requirements for different messages. So rather than having hard coded namespaces in the Message implementation, it would be nice to actually pass an array of namespace strings.

To do this I created a new set of classes that generically allow an array of strings to be attached.

The result is the [EnvelopeNamespaces] Attribute which you can use by explicitly adding namespaces like this using delimited strings in an array:

// CODEGEN: Generating message contract since the operation cancelShipment is neither RPC nor document wrapped.
[System.ServiceModel.OperationContractAttribute(Action="cancelShipment", ReplyAction="*")]
[System.ServiceModel.FaultContractAttribute(typeof(MarvelPress.Workflow.Business.RoyalShippingApi.exceptionDetails), Action="cancelShipment", Name="exceptionDetails")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(contactMechanism))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(baseRequest))]
[EnvelopeNamespaces(EnvelopeNamespaces = new string[] {
    "v1:http://www.royalmailgroup.com/integration/core/V1",
    "v2:http://www.royalmailgroup.com/api/ship/V2",
    "xsi:http://www.w3.org/2001/XMLSchema-instance",
    "xsd:http://www.w3.org/2001/XMLSchema"
} )]
cancelShipmentResponse1 cancelShipment(MarvelPress.Workflow.Business.RoyalShippingApi.cancelShipmentRequest1 request);        

Here's the more generic implementation:

public class EnvelopeNamespaceMessage : Message
{
    private readonly Message message;

    public string[] EnvelopeNamespaces { get; set; }

    public EnvelopeNamespaceMessage(Message message)
    {
        this.message = message;
    }

    public override MessageHeaders Headers
    {
        get { return this.message.Headers; }
    }

    public override MessageProperties Properties
    {
        get { return this.message.Properties; }
    }

    public override MessageVersion Version
    {
        get { return this.message.Version; }
    }

    protected override void OnWriteStartBody(XmlDictionaryWriter writer)
    {
        writer.WriteStartElement("Body", "http://schemas.xmlsoap.org/soap/envelope/");
    }

    protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
    {
        this.message.WriteBodyContents(writer);
    }

    protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
    {
        writer.WriteStartElement("soapenv", "Envelope", "http://schemas.xmlsoap.org/soap/envelope/");

        if (EnvelopeNamespaces != null)
        {
            foreach (string ns in EnvelopeNamespaces)
            {
                var tokens = ns.Split(new char[] {':'}, 2);
                writer.WriteAttributeString("xmlns", tokens[0], null, tokens[1]);
            }
        }
    }
}

public class EnvelopeNamespaceMessageFormatter : IClientMessageFormatter
{
    private readonly IClientMessageFormatter formatter;

    public string[] EnvelopeNamespaces { get; set; }

    public EnvelopeNamespaceMessageFormatter(IClientMessageFormatter formatter)
    {
        this.formatter = formatter;
    }

    public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
    {
        var message = this.formatter.SerializeRequest(messageVersion, parameters);
        return new EnvelopeNamespaceMessage(message) {EnvelopeNamespaces = EnvelopeNamespaces};
    }

    public object DeserializeReply(Message message, object[] parameters)
    {
        return this.formatter.DeserializeReply(message, parameters);
    }
}


[AttributeUsage(AttributeTargets.Method)]
public class EnvelopeNamespacesAttribute : Attribute, IOperationBehavior
{
    public string[] EnvelopeNamespaces { get; set; }

    public void AddBindingParameters(OperationDescription operationDescription,
        BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
    {
            //var serializerBehavior = operationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>();
            IOperationBehavior serializerBehavior = operationDescription.Behaviors.Find<XmlSerializerOperationBehavior>();
            if (serializerBehavior == null)
                serializerBehavior = operationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>() ;

            if (clientOperation.Formatter == null)
                serializerBehavior.ApplyClientBehavior(operationDescription, clientOperation);

        IClientMessageFormatter innerClientFormatter = clientOperation.Formatter;
        clientOperation.Formatter = new EnvelopeNamespaceMessageFormatter(innerClientFormatter)
        {
            EnvelopeNamespaces = EnvelopeNamespaces
        };
    }

    public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
    {
    }

    public void Validate(OperationDescription operationDescription)
    {
    }
}

Summary

Ah, WCF == (love && hate).

You gotta love that you can hook into the pipeline and fix a problem like this and that the designers thought of millions of intricate ways to manage the process of manipulating messages. But man is this stuff difficult to discover this stuff or even to hook it up. I was lucky I found a reference to MessageFormatter in an obscure post referenced in a comment.

While the code to actually do the work is really simple there is a boat load of ceremony around all of this code to get it to actually fire. Plus an attribute has to be added to each and every Operation method and it also means I have to manually edit the generated WCF proxy Client interface. All of which is as far from 'transparent' as you can get.

But hey, at least I managed to get it to work and now we can get on with our lives actually talking to the service. I shudder to think what other lovely oddities we might run into with this service, but I leave that for another day.

I hope this information is useful to some of you, although I hope even more that you won't need it, because you know, you shouldn't have to do it this way! But as is often the case, we can't always choose what crappy services we have to  interact with on the server and workarounds are what we have to work with.

So I hope this has been useful… I know my previous posts on WCF formatting issues are among the most popular on this blog. Heck, I have a feeling I'll be revisiting this post myself in the not so distant future since problem SOAP services are a never-ending plague these days…

Related Resources

Posted in WCF  Web Services  

The Voices of Reason


 

Ryan O'Neill
June 29, 2016

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Brilliant Rick, I was just coming to this conclusion and your post saved me a lot of digging.

Reading through this I thought it sounded familiar (an IBM API etc.). Then I see you bumped into the exact same issue with the exact same service (Royal Mail API).

It amazes me how bad these people are, the REST equivalent would be a fraction of the hassle. But someone from IBM sold a very expensive solution to Royal Mail instead, that does not even work properly.

Ryan O'Neill
June 29, 2016

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Also, you can attach behaviours programmatically instead of editing the generated code.

See http://stackoverflow.com/questions/35039413/royal-mail-shipping-api-c-sharp/38098233#38098233

Ash
November 17, 2016

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Run into this issue with the Royal Mail API last year. Your solution is very similar to what I come up. I would advise against editing the WCF generated files though. Implement an IOperationBehaviour class instead which makes use of the message formatter and attach this to each operation as a behaviour. My solution for Royal Mail DMO C# using SOAP can be found here: http://stackoverflow.com/questions/31595770/c-sharp-wcf-namespaces-move-to-header-use-ns-prefix


Brandon Duncan
March 23, 2017

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Rick, great article. I understand the gist of what you are doing, but I am having trouble implementing. I was looking at your companion answer at http://stackoverflow.com/questions/36230835/wcf-client-forcing-global-namespaces and I do not understand the following statement : "To hook this up, I added the attribute to client method on the service interface - in this case in my generated WCF client in Reference.cs." I am not sure where to do this in my project. I am using a Service Reference to call my Web Service. Would you mind explaining a little more by what you mean by "generated WCF Client"? Are your referring to a service reference? If not, then what? If so, how do you "add the attribute to the client method on the service interface"?

Thanks,

Brandon


Rick Strahl
March 24, 2017

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

@Brandon - WCF creates a code for a 'Web Reference'. If you look in your obj folder you'll find Reference.cs which is the generated code. You can pick up that file, add it to your project directly and modify and you'll get the same behavior as the Service Reference. That's the file I add the custom namespaces to.

Note when you do this you lose the ability to re-generate the service. There may be other ways to do this as well by subclassing or creating a separate interface and attaching that without explicitly changing the generated code, but either way you have to override what WCF generates.


Duncan Brandon
March 29, 2017

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Rick, thanks for the additional information. I still could not get it to work. Is the source code for this article available for download?

Thanks,

Brandon


Rick Strahl
March 29, 2017

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

@Brandon - no source since this came out of a proprietary project, but the relevant code is all here in the article.


Michael Christensen
April 04, 2017

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Rick, thanks for this article - looks like just what I'm looking for. However I'm having a problem working out what "baseRequest" and "contactMechanism" is. I cannot find them in your code and I cannot work out what to put there. Without the two lines everything seems to be working fine, but the prefix'es and namespaces isn't used. In my case it is a response that needs the prefixes.

Thanks Michael


Rajeev Ranjan Tiwary
August 17, 2017

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Hi Rick,

Very Nice Article. Can you elaborate following lines:

There may be other ways to do this as well by subclassing or creating a separate interface and attaching that without explicitly changing the generated code, but either way you have to override what WCF generates.

Can you give us some examples explaining other ways to override? Because there's no point of applying to Reference.cs as you also mentioned "you lose the ability to re-generate the service".


Jonathan
October 04, 2017

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Hi Rick

After a while searching i have found the solution based on your post. Thank you soo much.

I do have a question, would there be a better way to attach the behaviour in the code as opposed to the reference.cs as it would be lost if regenerated?

Thank you again, you have saved me soo much time trying to figure out what was in fact going on with the messages!


Rick Strahl
October 04, 2017

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

@Jonathan - You can subclass the service and then override each method and add the attributes there and just forward the calls to the base class. It's a bit of work but that would work. Then again you can easily run into trouble with that too as you have to make sure if the contract changes that you update attributes as well.


M Koerner
January 09, 2018

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Another solution would be to correct the WSDL and add elementFormDefault="Qualified" to all complex types. This would require namespace prefixes as needed.

Default value of this attribute is "Unqualified" which means no namespace prefix needed - WCF is correctly interpreting the WSDL here and using a global namespace (xmlns=..) for the complex types.


M Koerner
January 09, 2018

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Alternatively, in the generated .NET client code, change XmlElementAttribute Form = System.Xml.Schema.XmlSchemaForm.Unqualified to Form = System.Xml.Schema.XmlSchemaForm.Qualified.

This will force xx: namespace prefixes.


Felipe
August 31, 2018

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Hi Rick, Thanks for the example, works great as always. Just a little question how can i change the <h:Security></h:Security> prefix to wsse:Security</wsse:Security> ?

Thanks in advance.


Allen Salinas
November 16, 2018

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Thank's a lot for this information. After many days trying to figure it out, this post helped me to do it. Again, thanks from Colombia.


Simon Price
June 17, 2020

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

I am having some trouble getting this to work in .Net 4.7.2 WCF Application. I have followed the steps you mention here exactly and cannot get the output to change.

I have created the 3 files as suggested and added the attribute to the method that will be calling it however I do not have a references.cs file either as the service was mainly created from the WSDL file as we are taking over \ re-rewriting a service from a client.

I need to change the prefixes from s:envelope to SOAP-ENV:Envelope and add some namespaces into this object too.

Can you offer some suggestion?


Federico Rossi
October 13, 2020

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Amazing job Rick, thanks for the explanation. I have a doubt, is there any way to ignore or skip null values when serializing? thanks


Jorge
March 18, 2021

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Hi! Thank you so much for this, the only issue is when I use the generic implementation the namespaces appear on the body and not on the Envelope ):


Spencer Swindell
June 16, 2021

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Just wanted to say thanks for this post! I'm working with a SOAP API that presents the same challenges you faced here, and your post helped me get it working. Thanks for the walkthrough and explanation!


Giorgi Chakhidze
February 13, 2024

# re: Custom Message Formatting in WCF to add all Namespaces to the SOAP Envelope

Funny thing is, I have the exact opposite problem (with CoreWCF): need to move namespace declarations down to individual message elements.


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024