I am in a bit of a pickle with a current project. We have an integration partner who is refusing to conform to contract, and they are expecting a fault contract with custom headers, rather than the WSDL-defined message contract that includes the same headers and a contractually valid message body. It is not a problem to send a SOAP fault with WCF, as one can simply throw FaultException
. The real bind is the requirement that the fault contain custom headers. I was able to serialize a custom header by using the OperationContext
, however it does not serialize the way our integration partner requires.
Using OperationContext.Current.OutgoingMessageHeaders
, it is possible to create a custom MessageHeader<T>
that contains the object you wish to include in the header...it can be a POCO, DataContract, or MessageContract. When using a message contract, namespaces seem to get ignored, and the serialized message has a bunch of invalid xmlns= attributes on each member of the message, which is also a problem. Once a MessageHeader is created, calling the .GetUntypedHeader(name, namespace)
method will generate a MessageHeader
that can be added to the OperationContext's OutgoingMessageHeaders. The problem is that you can't add an object to the headers directly...they apparently must always be wrapped, since the GetUntypedHeader method requires a wrapper element name and namespace.
The required header is as follows:
<SOAP-ENV:Header>
<imsx_syncResponseHeaderInfo xmlns="http://www.imsglobal.org/services/lti/xsd/CoreOutcomesService_bv1p0">
<imsx_version>UNUSED</imsx_version>
<imsx_messageIdentifier>12345678-abcd-1234-ef00-1234567890ab</imsx_messageIdentifier>
<imsx_statusInfo>
<imsx_codeMajor>failure</imsx_codeMajor>
<imsx_severity>error</imsx_severity>
<imsx_messageRefIdentifier>12345</开发者_C百科imsx_messageRefIdentifier>
<imsx_description>yadda yadda some error message here</imsx_description>
<imsx_codeMinor>
<imsx_codeMinorField>
<imsx_codeMinorFieldName>SomeCodeName</imsx_codeMinorFieldName>
<imsx_codeMinorFieldValue>somecode</imsx_codeMinorFieldValue>
</imsx_codeMinorField>
</imsx_codeMinor>
</imsx_statusInfo>
</imsx_syncResponseHeaderInfo>
</SOAP-ENV:Header>
If it was not for the fact that the header, imsx_syncResponsHeaderInfo
, has three child elements, we would probably be in business. However, it is impossible to create a message header directly that wraps three separate objects, and when using a MessageContract with IsWrapped=false
, every direct child element of the imsx_syncResponseHeaderInfo
element gets serialized with an xmlns
attribute that defines an incorrect namespace (it seems to take the TNS of the service contract). That makes the header invalid according to the contractual schema, and the consumer cannot deserialize it.
Is there some way to add a MessageContract to the outgoing message headers of a WCF-delivered SOAP Fault, without requiring that it be wrapped, and such that the child elements to not get serialized each with their own xmlns attribute containing the TNS of the service contract?
As noted above:
The issue was actually due to how a business partner was deserializing our message contents. They did not want to take responsibility for the issue at the time, and the burden fell on my team and I. We finally managed to get them to fix their own issue, so we never actually had to solve the problem.
精彩评论