It seems that .Net 2.0 web services do not handle soap:mustUnderstand attribute in a consistent manner. This attribute can appear over soap headers in order to require the processing party to fail itself if it cannot process this specific header. Example:
Now if our server does not understand SomeHeader an exception should be thrown.
To begin with, when a SoapHeader is defined in the service/proxy, .Net will not allow us to mark it as "required" since it is considered obsolete:
This is not really related to mustUnderstand: When the proxy contains required=true it means (or should have at least) that the proxy will fail itself if this value is not supplied by the user. This is different than omitting a mustUnderstand header which will cause the server to fail.
But the real inconsistency comes with mustUnderstand: When a .Net 2.0 web service gets soap:mustUnderstand header it will always ignore it even if it was not understood. On the other hand, when a .Net 2.0 web service client gets such an header in a response from the server it will throw the following exception:
Be aware of this inconsistency when you build or consume .Net 2.0 web services.
In xml an element can be both optional and nillable:
So in xml this element can have a value:
Be NULL:
Or be omitted at all:
This is a challenge to many web services frameworks since when generating proxy code an element is usually mapped to one language variable. A variable in a programming language does not natively support metadata such as being "nullable" or "optional".
In some frameworks the solution is to add a "controller" field. For example some Java frameworks would create something like this:
In .Net 2.0 part of this informaiton is in a controller field and part in .Net attributes. For example a nillable string is:
And an optional int is:
What happens in .Net when an element is both nullable and optional? There is no problem with an int - we can use System.Nullable:
So now "i" can both have a value of null and seperately be specified as ommited.
String is more challenging since it can have null from the first place so "string?" is meaningless. We would expect to have:
However for some reason .Net does not generate this for the client side so it does not support out of the box a string which if both optional and nullable. The solution is to manually add the sSpecified element and the XmlIgnore attribute as above to the client proxy or the server side code. Note: For the client proxy updating the service reference will override any such change so use this method only if you have no other choice. For example use it when you try to interoperate with a framework that requires this.
Let's say you want your .Net 2.0 web service to return a simple string without any wrapping element (except the necessary minimum). Like this for example:
If you will use the default service template:
You'll get a string wrapped with an element "HelloWorldResult":
So how to return a raw unwrapped text? Just add the "return" attribute in this way:
WCF logging is a very important debug feature in .Net 3.5. However you shouldn't always trust what you see...
Removing nonce and passwords The first case where the logging may mislead is when security mechanisms such as username, password or nonce are used. For security reasons the log will no show them (see image bellow)
No WS-Addressing The WS-Addressing standard is used in some of the bindings. When it is not used (as in basicHttpBinding or certain customBinding) the log will still show you something like:
However this will not go on the wire as can be proved with fiddler:
This can actually also be proved by turning the WCF logging at the transport level:
So we can't really say that WCF showed something wrong here - after all the service level logging does not go on to the wire - but it is confusing.