Modifying SOAP requests with GetWebRequest - c#

I am trying to dynamically modify XML data in SOAP requests to ASMX services.
I overrided GetWebRequest() method in SoapHttpClientProtocol class in order to read and modify XML data that the RequestStream contains.
The problem is, the request seems to be empty, there is no data in it whatsoever. Is this because the SOAP data hasn't yet been generated and serialized or am I doing something wrong?

What you need is a SoapExtension. You could hook into the SoapMessageStage.AfterSerialize stage in ProcessMessage to modify your soap message. I've done this in the past to add WSSE headers in situations where I couldn't add a dependency on Microsoft's WSE library (since it isn't available for Mono).
Complete tutorial here: http://msdn.microsoft.com/en-us/magazine/cc164007.aspx
GetWebRequest is too early for your purpose, GetWebResponse is too late.

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.

Read SOAP XML message sent as HTTP message body

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.

Implementing a SOAP web service

I have a WSDL definition for a SOAP service and I have successfully generated *.cs file from it using SvcUtil.
Implementing client is quite straightforward - I just need to call the necessary functions from the generated *.cs and that's it.
Implementing server seems more complicated. As I understand I need to implement an interface from the generated *.cs and then use some magic to turn it into the web server.
But I don't need a new web server, I already have a web server written in C# which already has many functionality unrelated to the SOAP service that I need to implement. I don't want to create another web server but I want my SOAP service to be just a part of my existing application (server), that is my server can answer e.g. requests http://example.com/request1, http://example.com/request2 etc. and I want this SOAP service to be just http://example.com/request3.
Since HTTP is already handled by my server I don't need .NET to handle it for me, basically my server can accept client connections and call the necessary handler based on the URL. I have a handler for SOAP request which looks approximately like this:
MyResponse HandleSOAPRequest(MyRequest request)
{
// 1. parse soap message from request.body
// 2. process it
// 3. generate response, serialize it in SOAP format and return it
}
The question is - can I rely on WSDL definition and .NET libraries to do it?
Currently I'm parsing SOAP request using XDocument and manually extract fields from it and serialize using simple string concatenation. Using .NET built-in functions to serialize or parse XML doesn't work. That is if I try to serialize response from an object of the class defined in the generated *.cs file then produced XML is different from what is expected by the protocol, similarly, if I try to parse request as an object of the class defined in the generated *.cs file I get error because XML parser expects different format. This applies to both the SoapFormatter and XmlSerializer.
Since .NET can implement client this means that everything that is necessary to parse and serialize SOAP messages is already implemented, I just need to figure out a way how to use this functionality.
The documentation for ServiceModel wasn't very helpful.
The easiest way would be to start the service via the ServiceHost:
ServiceHost host = new ServiceHost(typeof(YourService));
host.Open();
(I assumed here the configuration will come from the app.config and will not be setup in code like in the linked example below.)
How to: Expose a Contract to SOAP and Web Clients
The only drawback of this is that the application has to run with admin rights or otherwise a weird cofiguration is necessary.

How can I consume odata using json with c#?

I'm consuming an odata v2 api with c# / winRT. It works fine, but it's using xml as encoding format for both read and write requests. How can I make it use json instead?
I've already tried attaching an event handler to myDataSource.SendingRequest, and adding an "Accept" header, but the client-side library explicitly intercepts this and throws an exception. Also, I could not find any "Accept" property on the client side.
Thanks,
Adrian
Assuming you're using the WCF Data Services client library (as per Phani's blog post), then this is currently not possible. The client library doesn't support JSON (yet).
If you really need to consume JSON you would need to use the ODataLib directly, which is not as "easy to use" as the WCF Data Services client, but it gives you more flexibility as well. ODataLib is the reader and writer for OData wire format. See this blog post for a sample. The ODataLib for Metro itself - Microsoft.Data.OData.Metro should already be part of the VS 2012 RC release.
You need to add an accept header to the request: 'accept: application/json'

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