Read SOAP XML message sent as HTTP message body - c#

I have a 3rd party that is sending SOAP XML messages, as the HTTP message body (using HTTP Post). I need to write a program to accept / process these messages.
I have a specification document which contains 2 WSDL definitions - GetTransaction and CutOff.
I am trying to use Postman to send a test message. Content-Type is set to application/xml and the body is set to raw / XML.
I am using C#, ASP.Net (4.7.2), the code is in a Class Library. I have a Controller (ApiController) with:
[HttpPost]
[ValidationAttributes.RequireHttps]
public HttpResponseMessage Service(XmlDocument reqData)
but reqData is always null. I have tried different types instead of XmlDocument.
Now if probably a good time to say that this is all new to me - I've not created a program to accept SOAP messages before.
Should I be creating a WCF Service Application (rather than a .Net Framework Class Library)?
I've tried adding the WSDL "definitions" but they don't seem to produce anything useful. E.g. there is reference to a "GetTransaction" method, but it has a parameter list of about 150 items!?
I have found quite a lot of stuff via Google but it always seems to be about sending, rather than receiving, SOAP messages.
I appreciate that I have not really included much code to look at, but I feel like I've started from the wrong place. So, any basic guidance, suggestions or links to tutorial sites would be most welcome.

Related

Is it possible to add http headers to a Soap request from the SoapExtension method ProcessMessage()

I am trying to add Digital Security headers to some api calls that leverage a third-party sdk. One of the required security headers is a hash of the entire POST body being sent. The sdk we are leveraging calls a SOAP endpoint and the construction of the soap envelope is very far along in the request process. The sdk offered some obvious BeforeRequest extension points but they are executed before the SoapEnvelope is constructed.
There are a couple ways I have attempted to solve this:
I was trying to take a serializable object and recreate the request with the soap envelope but doing so did not yield a matching string as there were namespaces that were applied when they shouldnt, encoding on innner objects serialization etc (I am sure I am doing things wrong but these struggles got me looking elsewhere)
Next I found the SoapExtension class and thought this would work for me. In my testing I am seeing that I get the full request body (with the SOAP envelope) exactly as it would be sent. But I do not think or cannot find a way to modify the http headers of this request from within the hooks in SoapExtension.
So the question I am asking here is focused on my second approach and wondering if this is possible. If not I will go back to my first attempt and see if I can figure out how to correctly generate an identical request body.

Proprietary bare-bone ASP web service

I want to create a proprietary minimal / bare-bone / data-light webservice. I prefer not to use the standard solutions like Restful, WebAPI, SOAP, WCF, etc.
I just want a web server listener that can receive and process 1 UTF8 string (own message format) and respond with 1 UTF8 string as the result.
My question is: can you give me a starting point, by providing a code example of the interface. Of course not the complete implementation.
Data transfer has to be as minimal as possible (no avoidable headers).
NB: Server language has to be .NET. Code example may be in C# or VB.
The most bare-bone thing to create a web service would be an HTTP Handler.
The sample I linked returns HTML but you could send back XML as well (or anything else really, just make sure to return an appropriate Content Type).
The call to your method would be a regular HTTP call of the URL of your Handler.

Return XML when consuming a secure web service

I am currently trying to consume a generated report as a webservice to integrate some data into our system. Because the service itself is generated, the response can change frequently as things are added to it. While the endpoint and response may change, the request body will always be the same (taken from soapui):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<Execute_Report>
</Execute_Report>
</soapenv:Body>
</soapenv:Envelope>
I'm trying to figure out a way to make the above request for any endpoint (different reports) and allow for changes in the response. Ideally, I want to just return the raw XML of the response as I can allow for change easier with how I handle the XML if I'm not being tied to a data contract.
It is also worth noting that the service uses WS-Security and a Username/Password is passed as part of the request.
I've used WCF and the files generated from svcutil work great when I don't expect the service to change frequently. However because these webservices are generated change is expected, and if I can get away from it, I don't want to be at the mercy of re-generating a new file with svcutil whenever things change, or have to generate a file (and maintain) for all the different generated webservices.
At the end of the day the question is: How do I consume a webservice and return the raw XML while still being able to apply WS-Security to the request?
I kept searching around and found this answer:
.NET client authentication and SOAP credential headers for a CXF web service
This allowed me to do what I was after.

Can unpredictably typed arguments be handled in a WCF service?

I'm relatively new to WCF services, so I apologize in advance if I'm missing the obvious. My business uses EasyPost as our shipping solution, and I've written a WCF service to handle the shipping status webhook calls from EasyPost, described here: https://www.easypost.com/docs/webhooks
Briefly, EasyPost sends an update object as JSON via POST. The problem is that it sends several different types of (non-configurable) updates to the same service method, and I'm finding it difficult to write a DataContract that encompasses all the possibilities. For example, if the argument it sends is a tracking number update, update.result.status will be a string value; if it's a batch status update, update.result.status will be an object. It's a bit of a mess.
I tried handling just the update type that I care about and returning a 400 status code on the others, but EasyPost interprets that as an outage and drops my service as a webhook endpoint.
From what I've read, it looks like I could abandon the comforts of a Data Contract in favor of using a System.ServiceModel.Channels.Message parameter as a catch-all, then parse the message manually. That doesn't strike me as a wise/clean solution, though.
I'd be grateful for any alternatives.
This is probably not the best way I could have handled this, but it works.
I have an HTTP Module that identifies whether the incoming request is for the proper service method, and if so, converts the ContentType header from "application/json" to "text/plain".
My service method accepts the content body as a System.IO.Stream parameter. By converting the stream to a byte[] and then to a string, I end up with the raw JSON string sent by EasyPost.
After that, it's just a matter of using Newtonsoft.Json to attempt to deserialize the JSON string into the expected Type.
Even if the deserialization fails, I can still log the data and send a success response to the caller. That's good enough for my purposes.

See the SOAP request from Proxy class method calls

I'm using .NET 2.0 web services. If I add a reference to a WSDL and make a proxy class method call, what's the easiest way in VS to see the SOAP being sent?
Example, I added the PayPal WSDL Web Service Reference and made a call as so:
PayPalAPIAASoapBinding _client = new PayPalAPIAASoapBinding();
...rest of code and then
SetExpressCheckoutResponseType checkoutResponse = new SetExpressCheckoutResponseType();
checkoutResponse = _client.SetExpressCheckout(request); // makes the call here
I tried setting a debug point on line 2 but not sure how to dive in to see the SOAP. Obviously I could use something like Fiddler but want to just use Intellisense during debugging to drill down to the object that has the request. I would assume client would have it, my instance above but could not find it. Client is an instance of the PayPal Service.
I do see when I drill down into the base class PayPalAPIAASoapBinding that there is a version property but I can't get the value for this:
System.Web.Services.Protocols.SoapProtocolVersion.Default
when I try to paste that into my watch window, the value just shows the word Default not the true value that's sent. So this is why I need to look at the SOAP and so far in that binding object I don't see a property holding it. But it's gotta be somewhere in any requests you make in a web service in .NET, just don't know where to look during debug?
My end goal here is to be able to read the SOAP envelop before it's being sent really using any WSDL reference in VS.
There's no very easy way. See the example in the SoapExtension documentation on MSDN for a way to log the information.
If you were using WCF, you could just turn on logging in the configuration.
The easiest way to see the SOAP messages (regardless of the programming language) is to use a tool like SoapUI or TCPmon which lets you intercept send and received messages.
This is very easy (if the SOAP is not encrypted). Although it is not in VS.
The easiest way is to use the Fiddler. You can let your VS make Soap calls and see the traffic in raw view on the Fiddler. If the Soap calls are made over SSL, there are some extra steps that needs to be taken for Fiddler to trace them.

Categories

Resources