I have implemented a message inspector in WCF by implementing IDispatchMessageInspector.
Putting a break point on this method...
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
// Impementation
}
... I can look at the request object to see what is inside.
Clearly I dont understand WCF enough because whatever endpoint binding I use (basichttp, nettcp and netpipe) the message inside is always represented in SOAP format e.g.
<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">
<s:Header>
-- headers --
</s:Header>
<s:Body>
-- body --
</s:Body>
</s:Envelope>
Is this because doing a .ToString() on the request object just represents the message in SOAP format?
I imagined that using another protocol e.g. netTcp would result in a different message payload.
Also lets say I wanted to represent my data in JSON format how would I go about doing this? Or would I end up with JSON formatted data structures inside a SOAP envelope?
It is because all bindings you mentioned are designed to use SOAP protocol. They are using either TextMessageEncoder or BinaryMessageEncoder and both these work with SOAP envelopes (except the situation where you use TextMessageEncoder in custom binding with MessageVersion set to None).
The only out-of-the box binding allowing other message formats is WebHttpBinding which uses WebMessageEncoder supporting both XML and JSON.
Related
Context
I am new to WCF.
I was reading an article about message contract and found that WCF is sending message using SOAP.
My doubt is, if we are enabled REST in WCF service, then will it still use SOAP format for exchanging data.
In WebGet and WebInvoke attribute[which are for REST], we are mentioning the inputformat like JSON or XML.
Question
If messages are sent through SOAP, then why are those needed ?
If all message contracts are sent using SOAP format, then message contract should not work in case of webHttp binding.
The protocol format will depend on the binding you select. Here's a list of the different system provided bindings and the underlying protocol they use.
In WebGet and WebInvoke attribute[which are for REST], we are
mentioning the inputformat like JSON or XML.
If messages are sent through SOAP, then why are those needed.
If you use the WebHttpBinding which uses standard HTTP instead of SOAP then those attributes allow you to specify whether you want to format the requests using plain XML (not SOAP) or JSON.
I'm not sure the title really gets across what I need to do. I want to force or coerce or whatever a WCF service to accept a slightly different SOAP message. Here is what the service expects:
<sch:modifyCandidateNotification>
<!--Optional:-->
<sch:request vueCandidateID="?" clientCandidateID="?" clientCode="?">
...
but here is what I want to send to the service:
<sch:modifyCandidateNotification vueCandidateID="?" clientCandidateID="?" clientCode="?">
I'm not responsible for sending the SOAP, one of our partners is and they can't alter what they are sending. I don't want the structure at all.
I've tried adding [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare)] to the interface, but to no avail. Also, I'm using a basicHttpBinding. I've tried with the wsHttpBinding and did not see any difference.
Thanks.
We are working on a third party integration using WSDLs and XSDs that were provided to us. We've used svcutil to generate all the proxy classes for us which works fine. When we test with SoapUi everything works fine, however, when we try to send the response to our partner they're rejecting the SOAP message because the namespaces are being defined in the message header and body rather than the SOAP envelope.
Unfortunately, I can't make our partner change their process to accept our messages (even though I believe they are technically correct since we are defining the namespaces before we use them in the XML, just not where they expect them). I know I could put a message inspector in to massage the SOAP message before goes out, but I'd rather not go to that level of processing.
Are there any settings either for svcutil or even on the serialization attributes that we could set to have WCF output the namespaces on the envelope instead?
What they want:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:h="http://theirdomain.org/service">
<s:Header>
<h:myType>
<version>V1.0</version>
</h:myType>
</s:Header>
<s:Body>
<h:someElement />
</s:Body>
</s:Envelope>
What we're sending:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" >
<s:Header>
<h:myType xmlns:h="http://theirdomain.org/service">
<version>V1.0</version>
</h:myType>
</s:Header>
<s:Body>
<h:someElement xmlns:h="http://theirdomain.org/service"/>
</s:Body>
</s:Envelope>
I think the right extensibility point for this may be a custom encoder (see http://msdn.microsoft.com/en-us/library/ms735115.aspx , or the samples at http://msdn.microsoft.com/en-us/library/ee960159.aspx , especially the first one). In the custom encoder, you would write the SOAP Envelope yourself (with the correct namespaces), and then call methods on the Message object to write out the headers and body (e.g. WriteBodyContents, see http://msdn.microsoft.com/en-us/library/ms734675.aspx - under "Writing Messages").
I need to create a WCF service that will emulate some third-party service. That service has very complicated messages and wrappers for them, so I will simplify them in description.
I have WSDL of that service and created proxy class. But here the first problem occurs: all methods in proxy have
[System.ServiceModel.OperationContractAttribute(Action = "", ReplyAction = "*")]
So it is impossible to create WCF service with many methods: each for one method in proxy because every method must have unique Action. I think that third-party service has one method that handles all requests. And I created such method with needed KnownType attributes on RequestTypeBase and ResponceTypeBase. All proxy-class methods have one parameter of type, derived from RequestTypeBase.
And here is the main problem and question: when WCF service tries to deserialize message body, it throws an exception saying that expected elementName is "Process" (the name of my mega-method that processes all requests) but existing elementName is "RequestType1" (the name class with data that must be passed to "Process" method as parameter). So how can I receive such message?? Is there some attribute in WCF to not require the methodName as root of Message body? And I even not understand for what does WCF need that MethodName there if he already knows what method is called? Looks like redundancy with action specification.
Maybe simple MessabeBody example that is successfully processing by WCF, will help to understand what I mean:
<s:Body>
<TestMethod xmlns="someNamespace">
<x>1</x>
<str>param2</str>
</TestMethod>
</s:Body>
You could skip WCF deserialization completely on the service side by using the "universal service contract":
[ServiceContract]
public interface IUniversalRequestResponseContract
{
[OperationContract(Action="*", ReplyAction="*")]
Message ProcessMessage(Message msg);
}
and then handle deserialization yourself working with the Message instance received.
If you are writing a stub emulation of some external service for testing purposes (I'm guessing), that is a good approach anyway because you can control exactly what is sent in the response.
Microsofts's WCF is easy to work with when you create Web services where each message has it's own Web method. WCF generates all of the WSDL and everything is easy.
What I want to do is have one Web method that accepts multiple different messages (I don't want to add a mew method every time I add a new message type). The messages themselves will have header information that identify the message type. Once I know the message type, I'll know the structure of the rest of the message.
The only way I've found to do this with WCF is to have the method accept a string, which I parse in as XML and and use. However, I can see no clear way to publish the various message types in the WSDL; so, the whole service is essentially undocumented.
Anyone know of a technique to use in WCF?
You can write an operation contract that accepts any message by setting the Action to * and having it take in a Message object:
[ServiceContract]
public interface IMessageContract
{
[OperationContract(Action = "*", ReplyAction = "*")]
Message ProcessRequest(Message request);
}
The Message object gives you access to the headers and has methods to deserialize the body.
To export your own WSDL, you will need to implement IWsdlExportExtension on a contract behavior or operation behavior and attach it to your service. This will give you access to a WsdlExporter, and you can create a ContractDescription yourself and call ExportContract to have it appear in the generated WSDL.