将数据协定写入 SOAP 信封标头以处理传出的FaultException?
我对当前的项目感到有点困惑。我们有一个拒绝遵守合同的集成合作伙伴,他们期望一个带有自定义标头的错误合同,而不是包含相同标头和合同上有效的消息正文的 WSDL 定义的消息合同。使用 WCF 发送 SOAP 错误不是问题,因为可以简单地抛出 FaultException
。真正的绑定是要求故障包含自定义标头。我能够使用 OperationContext
序列化自定义标头,但它没有按照我们的集成合作伙伴要求的方式序列化。
使用 OperationContext.Current.OutgoingMessageHeaders
,可以创建一个自定义 MessageHeader
,其中包含您希望包含在标头中的对象...它可以是POCO、DataContract 或 MessageContract。使用消息契约时,命名空间似乎会被忽略,并且序列化消息的每个成员上都有一堆无效的 xmlns= 属性,这也是一个问题。创建 MessageHeader 后,调用 .GetUntypedHeader(name, namespace)
方法将生成一个 MessageHeader
,可以将其添加到 OperationContext 的 OutgoingMessageHeaders 中。问题是您无法直接将对象添加到标头...它们显然必须始终被包装,因为 GetUntypedHeader 方法需要包装器元素名称和命名空间。
所需的标头如下:
<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</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>
如果不是标头 imsx_syncResponsHeaderInfo
具有三个子元素,我们可能会正常工作。但是,不可能直接创建包装三个单独对象的消息标头,并且当使用带有 IsWrapped=false
的 MessageContract 时,imsx_syncResponseHeaderInfo
元素的每个直接子元素都会获取使用定义了不正确的命名空间的 xmlns
属性进行序列化(它似乎采用服务契约的 TNS)。根据合同模式,这使得标头无效,并且消费者无法反序列化它。
有没有某种方法可以将 MessageContract 添加到 WCF 传递的 SOAP 错误的传出消息标头中,而不需要对其进行包装,并且子元素不会使用自己的包含服务 TNS 的 xmlns 属性进行序列化合同?
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</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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如上所述:
As noted above: