Altering a SOAP message before deserialization - c#

I'm having trouble intercepting a response message due to an invalid envelope. Unfortunately, WCF is throwing the exception "Unrecognized message version." before AfterReceiveReply is called so I don't have an opportunity to correct the response XML. Is there a lower level (or different) call I can use to intercept the stream and correct this XML or is there a better way to handle the response, i.e. CustomBinding?
I've tried IClientMessageInspector AfterReceiveReply and IOperationBehavior but these behaviors are both called after the exception is thrown.
Here's what the response looks like.
<ENVELOPE>
<HEADER>
<ERROR_CODE>955</ERROR_CODE>
<ERROR_DESC>XML Parsing Failed: test:1:74 error: value '1231231230' does not match regular expression facet '\d{19,20}'</ERROR_DESC>
<ASYNCH_RESPONSE_INDICATOR>0</ASYNCH_RESPONSE_INDICATOR>
</HEADER>
<BODY>
<MY_METHOD_RESPONSE></MY_METHOD_RESPONSE>
</BODY>
</ENVELOPE>

The service you are trying to call is not a SOAP service. It looks like an old style POX web service, in which case there are two ways you can consume it.
use a WCF POX client, or
use HttpWebRequst
To use WCF, refer to here and here. Your problem here is that these style of services are now considered unorthodox, so the later versions of WCF may no longer support them.
On the other hand, HttpWebRequest, while still supported in .net, is fiddly and not widely used. It does have a high-level wrapper called WebClient which is much easier to use, but it may not give you the level of control you need.
I would certainly investigate the second option first. The support for POX services in WCF was brought in in 2008 with the REST Toolkit, Microsoft's initial foray into the world outside SOAP services (.net remoting notwithstanding), and so is seriously dated.

Related

.NET SOAP communication with separate certificates for signing and encryption

I try to configure client communicating with SOAP service written in Java, yet I failed so far. While it's pretty easy to connect with that service using SoapUI (I just need to put these two certificates in adequate places and it just works) it's pretty far from being easy (and intuitive) in C#.
Service uses two different certificates - one for signing message (binary token) and one for TLS encryption. I implemented my own classes for that thing using this tutorial:
https://learn.microsoft.com/pl-pl/dotnet/framework/wcf/extending/how-to-use-separate-x-509-certificates-for-signing-and-encryption
Thanks to that I'm able to connect and send request, but that's not the end of the problems. Next error was "The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected."
According to my research I should just erase whole Security header and configure my client to allow unsecured response. Therefore I should implement my own MessageEncoder what I actually did using this:
https://learn.microsoft.com/pl-pl/dotnet/framework/wcf/samples/custom-message-encoder-custom-text-encoder
I only added one extra function that should erase security header, just like #nuronce did in this thread:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/16de05ed-3776-40e5-b576-139603e4b374/the-incoming-message-was-signed-with-a-token-which-was-different-from-what-used-to-encrypt-the-body?forum=wcf
But that's still not the end of the problems... Right now it says: "The message version of the outgoing message (Soap11 (http://schemas.xmlsoap.org/soap/envelope/) AddressingNone (http://schemas.microsoft.com/ws/2005/05/addressing/none)) does not match that of the encoder (Soap12 (http://www.w3.org/2003/05/soap-envelope) Addressing10 (http://www.w3.org/2005/08/addressing)). Make sure the binding is configured with the same version as the message."
That's weird because in every place with MessageVersion property in my custom encoder classes it's set to MessageVersion.Soap11 as default value that should not be modified, because I don't change anything in my CustomTextMessageEncodingBindingSection.
For every solution WCF gives me another problem and I'm losing my patience for that, because these solutions are not so easy to find and adjust to my needs. I'm also pretty sure that even if I go through my current problem - I will find another one, maybe harder or even impossible to resolve.
Are there other .NET libraries that will allow me to use two different certificates by default and save my code from growing, hard to understand convolutions? And if there is none, how can I deal with WCF?

CallBack Contract and Binding

I have my service on a web site. I try to run this example, first just the server part:
:What steps do I need to take to use WCF Callbacks?
But I get this message: "Contract requires Duplex, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it."
The Web.config file, doesn't have definitions such 'BasicHttpBinding'. It only has more general defitions. Do i have to add lines to it, or there is a more simple way. Many thanks.

Returning a custom formatted SOAP message from WCF

I have a requirement where a method call on a WCF service has to return a SOAP message in the format below:
<soap:Body>
<m:RequestProcessed xmlns:m=" ">
<m:Status>OK</m:Status>
<m:UID>subfolder name</m:UID>
</m: RequestProcessed >
</soap:Body>
Can this be done with Faults, if so please give some pointers on where to look.
If not then what is the alternate?
Appreciate your time.
Regards.
Once I had very similar question: Controlling WCF Message Body serialization
Probably the answer will help you too (please note it requires WCF 4).
The alternative is writing directly to the response streem even without need to work with abstract Message object. This approach is described in this thread: WCF 4 REST - Acquiring the underlying response stream object for writing

Returning results/erros from WCF services. Complex type or an exception?

A few days ago I asked a very similar question. I was about returning values/errors inside the application. I accept an answer to not return error as and object but throw an custom exceptions.
Now, I'm not exactly sure how to deal with it using WCF services. I wish the service will be as simple as it could be for client.
Speaking very generally, my project looks like that:
Client -> WCF Service application -> Database.
Inside WCF app I've got my own exception class, and it works fine. But let's say client want sth from db. My question is:
What should I return to the client outside my app?
A. Complex type: A value with meta data (information about a possible error[1]). And when really unexpected error occurs throw an exception.
B. Just a value (when possible error occurs - throw an exception)
[1] - invalid string format, can't connect to database or sth like that. I mean - If I know what the error exactly is - why throw an exception to client - I'm not sure about that.
The decision how to tackle this problem depends on the client. If you have to support Silverlight Clients, throwing exceptions is out of the picture because Silverlight Clients using the browser HTTP Stack cannot deal with them. For Silverlight Clients I generally recommend (and use myself) the approach described here.
By design, WCF hides exceptions from the client. It's up to the developer to determine what, if any, information is returned to the client when an exception occurs.
I would look at using FaultContract or FaultContract<T>, and return exceptions that you wish to via that mechanism.
Here's some articles to look at:
Fault Contract
WCF Tutorial Fault Contract
You might also want to look at IErrorHandler for WCF:
IErrorHandler Interface

Semi-custom WCF proxy returns zeros, despite valid data coming back on wire

There is a series of SOAP services which I wish to call (across a series of services), and while the end points are well defined & documented, there is no WSDL data... so I decided to build my own.
In order to do so, I built a test WCF service which matches the known interface of the service I wish to call.
I then saved the WSDL it exposed, changed the base address the WSDL references, created my proxy (with wsdl.exe), added it to a test client project, and can successfully create a proxy and make calls which causes the SOAP service to send the expected response... only this expected response is not picked up by the proxy and returned to the calling code.
When looking at the back and forth traffic... I can clearly see that the service is replying with what I want.
Any suggestions as to how I might troubleshoot this and get the proxy to pickup the data?
Given the replies are effectively identical, I'm forced to look back at the differences between what my client is sending and another sends.
A known working app sends it's XML blob starting with the following:
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
While my client immediately starts with the envelope (without the xml tag, and with one less namespace):
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
The other difference is that the message within the body is prefixed by a namespace in theirs, while mine it is not... though both define this namespace within the tag.
Ala:
<s:Body>
<u:DoSomething xmlns:u="urn:http://some.namespace.org" />
</s:Body>
VS:
<s:Body>
<DoSomething xmlns="urn:http://some.namespace.org" />
</s:Body>
This is not a namespace:
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
It's setting the encoding style for the envelope which, even though it's not required per the SOAP spec, may be required by the specific implementation you're talking to. Do you have enough control over what you're sending from the client to get that put on there?
Other than that, the XML PI is not required and I think you're definitely on the right track looking at the body XML. This is almost always the case of some kind of namespace mismatch somewhere. Are you 100% positive the namespace URIs are identical?
The most likely problem is the VS version using a "default" XML namespace. There are soap parsers that I've worked which don't work correctly when using an un-aliased (default) namespaces. If you know using the u: alias works with the service, your proxy should also generate it even when every tag inside the s:Body element is prefixed with the alias.

Categories