Writing a data contract to the SOAP envelope headers for an outgoing FaultException? - wcf

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?

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.

Related

Is there a way to get raw message from MassTransit?

I have a consumer with generic argument IEvent. This type is a base interface for all messages, and child interfaces of IEvent have some other properties. I'd like to have access to the raw message with all properties of nested types instead of only IEvent scope. These properties can be seen through RMQ admin dashboard and I think there should be a way to put them out.
You could use context.TryGetMessage<T>() to request the specific type, which essentially attempts to deserialize the message into the specified type (as long as it is in the list of messageTypes serialized into the header).
Otherwise, you can use context.TryGetMessage<JToken>(), and get the JToken from JSON.NET, which can be used to navigate the message body.
Honestly, this isn't the best approach to properly handling events, etc., so I'd refer to the documentation to see how to properly consume the various message types (and let MassTransit do the hard work).

Pass polymorphic type as argument in SoapUI when using ServiceKnownType in WCF Service

I have a WCF Service; this service has an operation that receives an argument of type Request. This is only the base type, and when calling the operation we actually send a value of type Request_V1 (which inherts from Request), that has the complete implementation of the request I want to send.
When trying to test the service using soapUI, I'm able to create the complex type of type Request_V1 (adding the proper namespace) but for some reason, the service is receiving the value as if it were of Request type.
Reading about ServiceKnowType, I found out here that I need to specify somehow explicitly in the client this inheritance relationship, but I haven't found any info regarding how to do it on soapUI
Has anybody experienced and solved the same issue?
Thanks
You also have to specify the type in the SOAP message.
For example
<Request i:type="d:RequestV1">
...
where i is defined as XML-Instance namespace
On service side, you need to typecast to specific derived type.
operation (Request request){
if(!(request is Request_V1)){
throw Excetion("Unknown type!");
}
var request_v1 = Request as Request_V1;
// use request_v1
}
On SOAP UI side, specify type as below:
<soapenv:Body xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ns1:OperationName>
<ns1:request i:type="ns2:Request_V1">
Make sure you have defined ns1 and ns2 before referring to them.
You don't specify the inheritance in the client, rather in the service. SOAPUI shouldn't have a problem with that. Check you have the correct declarations on your data contracts. This might help - Deserialize Abstract Class.

WCF Custom Message implementation

In the context of a WCF project, I need to handle in the same way xml and non-xml messages (eg. Standard SOAP, WS-Attachments, etc..). The normal flow of WCF creates a Message object which can handle an Xml message, this is done by the encoder, so if one wants to handle different messages, it's needed to implement different kind of message-handling...
My needs is to create a message derivation class, which represent the concept of "received message" but not "handled" in the form of special data handling, but , about real data-handling, deferred in a secondary step.
so in the catch-all service I will get a Message messageObject as parameter, so the signature of the service will be Message Accept(Message messageObject)
Any idea?
thanks in advance
There is only single base Message type in WCF. This is a core type which is used by WCF infrastructure. The type is abstract so generally you can create your custom implementation but in such case you will probably have to replace some WCF channels to correctly use your new type.
If you need to transport message in custom format you are probably not looking for replacing Message type but either replacing encoder, serializer or both.

MsmqIntegrationBinding Serialization with Unknown Message Body Types

I'm looking to use the MsmqIntegrationBinding to integrate with a legacy queue which has a serialized object as the message body. Has anyone come up with a way to obtain the "metadata" of the message body and create a service side class to use within the service?
For example, if I put in a serialized Product object from System A and my service needs to consume it, how do I provide MsmqMessage the type if I do not have the Product class on my side? I was thinking of reading off a message in a separate program, deserializing, and then emitting via the code dom. Ideas?
I wholeheartedly recommend against attempting to emit the deserialized type at runtime in the message destination. Either work with the XML at the destination to obtain the data you desire, or build data contracts that both the source and destination can adhere to.
Hmm... in WCF, you can define service methods which take (and optionally return) an untyped Message type. This seems to fit your bill quite nicely.
Other than with strongly typed messages, you'll have to do all the putting together of the message on the client and the taking apart on the server by means of reading the raw XML - but that seems to be what you're looking for, right?
Find more information and samples here:
WCF - Handling Generic Messages
How to pass a generic object through WCF
Untyped messages on WCF
Untyped messages have some restrictions, e.g. you can only read them once on the server, but you should be able to manage your scenario with this, I think.
Marc

Creating WCF messages with mutiple namespaces

I'm trying to create a WSTransfer implementation (I realise Roman Kiss has written one already for WCF - but it doesn't actually meet the specifications)
I've ended up abandoning data contracts on the service contacts because WSTransfer is loosely coupled; so each the create message looks like Message Create(Message request).
This works fine, and everything is lovely until it's time to fire back a response.
The problem I have is in the way a WSTransfer response is constructed. Taking create as the example the response looks like
<wxf:ResourceCreated>
<wsa:Address>....</wsa:Address>
<wsa:ReferenceProperties>
<xxx:MyID>....</xxx:MyId>
</wsa:ReferenceProperties>
</wxf:ResourceCreated>
As you can see there are 3 different XML namespaces within the response message.
Now, it's easy enough when one is involved; you can (even if you're not exposing it), create a data contract and set the values and fire it back
Message response = Message.CreateMessage(request.Version,
"http://schemas.xmlsoap.org/ws/2004/09/transfer/CreateResponse",
resourceCreatedMessage);
However the problem arises in setting different namespaces for the child elements within the response; it appears WCF's datacontracts don't do this. Even using
[MessageBodyMember(Namespace="....")]
on the individual elements within the response class don't appear to make any changes, everything becomes part of the namespace specified for the contract class.
So how do I apply different namespaces to individual elements in a WCF Message; either via a contract, or via some other jiggery pokery?
In a case like this when you need precise control over the XML output, you should use the the XmlSerializer instead of DataContract or MessageContract serialization. Here is more info on how to do that:
http://msdn.microsoft.com/en-us/library/ms733901.aspx
So following up jezell's answer; the problem with using XmlSerialization when creating a message by hand is that the child elements of the root get their element names mangled. This happens because despite the operation contract being marked as [XmlSerializerFormat] when you create a message by hand the DataContractSerializer is used.
You cannot pass the XmlSerializer into Message.CreateMessage() because it demands an XmlObjectSerializer, which XmlSerializer is not.
So the answer appears to be write a wrapper class for XmlSerializer, which has XmlObjectSerializer as its base class (here's an example) and pass that in; along with your message holding class.
Unfortunately it's not clever enough to setup prefixes in the XML; so you end up with messages like
<ResourceCreated xmlns="http://schemas.xmlsoap.org/ws/2004/09/transfer" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing/">http://localhost:8731/Design_Time_Addresses/AddTests/WSTransfer/</Address>
<ReferenceType xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing/"></ReferenceType>
But it's all equivalent.