When responding to requests using any of the text/XML bindings (BasicHttpBinding / WSHttpBinding / CustomBinding with a TextMessageEncodingBindingElement), WCF has some specific prefixes which it uses corresponding to a certain namespaces. The SOAP namespace (“http://www.w3.org/2003/05/soap-envelope” for SOAP 1.2, “http://schemas.xmlsoap.org/soap/envelope/” for SOAP 1.1), for example, is always mapped to the prefix “s”. This is usually not a problem, but there are some Web Service stack implementations which require that a certain prefix to be used (there have been a few questions in the WCF forums about this issue.
First a small introduction on why this should not be a problem. The following two documents are essentially equivalent, from a XML Infoset standpoint, for “namespace-aware applications”, according to http://www.w3.org/TR/xml-infoset/#infoitem.element:
Here, the only difference between those two documents is the prefix used to represent the namespace “http://my.namespace”. So, I imagine that the WCF developers decided to follow that “rule” and didn’t add any simple way of changing the prefixes used in its SOAP responses – after all, it shouldn’t matter. The problem is that sometimes it does :-). Thankfully, the WCF extensibility model is rich enough that we can overcome this limitation by a number of different ways. Here I’ll show one which uses the message encoding extensibility to trap the message right before it’s encoded into bytes (to be sent over the wire), modify it changing its prefixes when necessary, and then proceed with the encoding.
The code for this post can be found in the MSDN Code Gallery at http://code.msdn.microsoft.com/Replacing-XML-prefixes-in-a417c6f2.
The class PrefixReplacer does most of the work, by using the XmlElement class to change, whenever necessary, the elements / attributes of the XML document which have the prefix which needs to be changed.
The encoding element follows a pattern similar to the custom message encoder found in the WCF samples at http://msdn.microsoft.com/en-us/library/ms751486.aspx. Essentially, it simply delegates all calls to an inner encoder, except when writing messages to the wire; in this case, it will instead first change the message (to replace the prefixes, then call the inner encoder to convert it to bytes.
This example shows one way to use this new encoding. Notice that to really see the prefixes changed, you’d need to use a network sniffer, such as Fiddler (which is, by the way, one of the most useful tools I use at work).
Notice that in the example above I set the message security to None in the WSHttpBinding constructor. If you try using a binding which uses message security (such as WSHttpBinding with its default constructor), this prefix changer will not work. The problem is that the default security causes the original message to be signed, and a signature header to be added to the message itself with a (signed) hash of its contents. By changing the prefix of the XML we’d be invalidating the message signature. There are some ways to circumvent this problem, such as implementing the changer as a custom channel which sits on top of the security channel, so that it would change the XML prefixes before the message is signed. Building a custom channel requires a lot more code than a custom encoder, but if you really need it you can definitely do it as shown by the Custom Message Interceptor sample from http://msdn.microsoft.com/en-us/library/ms751495.aspx.