Get SOAP request body in proxy client - c#

I have application which calls a WCF service. For monitoring and tracking purposes I would like to have log all request messages for which application failed to call a service. Loke I need to call operation called RemoveSubscription and once failed(may be network problem or WCF service was down) I would like to log the SOAP message into xml or txt file.
Generaly is it possible to get the request SOAP contact in proxy class.
I found some info that it can be done by extending SoapExtension class. If this is the right way how to register/inject the new class which extends SoapExtension to channel stack.
EDIT : Service is not hosted in IIS it is in Windows service... so I am i right that in this case SoapExtension is not the right solution.

With a WCF based client, you can create an endpoint behavior to intercept the request & response messages. This TechNet article shows how to access the message being sent and the response message. Your WCF client can be generated by either adding a Service Reference in Visual Studio, using SvcUtil to manually generate your client code or rolling your own proxy directly in code using the ChannelFactory class.
Your logging code would always write out the request message with a status of requested and a timestamp to some data store (file, database, etc.) When the response message is received, it would match request message somehow from the response message contents and update the data store to change the status to responded. Selecting all the messages from the data store with the status of requested older that some time period would list all the failed messages.

Related

JSON Decoder in custom pipeline is not working

I am using BizTalk+ESB. I send a request to a REST service. Using this pipeline.
Which uses the JSONEncoder. The rest service posts a message in the event log, letting me know the process was completed. The issue is, on the response, I get this error:
"The content type application/json; charset=utf-8 of the response message does not match the content type of the binding (application/soap+xml; charset=utf-8)."*
This is the response pipeline:
It acts as if the JSONDecoder is not processing the response message.
The request is made using ESB Itinerary, and a WCF Web Service in BizTalk.
Any suggestions?
UPDATE - The call to the Rest service is in an Itinerary Service. WCF_WebHttp was not in the list of selections. Selected WCF-BasicHttp.
Now I receive the error: "There was a failure executing the response(send) pipeline: "PTwoMapPipeline.Part2RetMapPipeline, PTwoMapPipeline, Version=1.0.1.3, Culture=neutral, PublicKeyToken=7de7b3b357ccad5e" Source: "XML assembler" Receive Port: "WcfReceivePort_WCFInitiator/Service1" URI: "/WCFInitiator/Service1.svc" Reason: The document type "http://schemas.xmlsoap.org/soap/envelope/#Envelope" does not match any of the given schemas."
on the return Pipeline in my receive location. (Two way). Does this mean I need to add an Envelope schema. The Message is set in Receive location to use the body.
You need to use the WCF-WebHttp Adapter for a RESTful service. See WCF-WebHttp Adapter (Microsof.com)
Microsoft BizTalk Server uses the WCF-WebHttp adapter to send messages to RESTful services. The WCF-WebHttp send adapter sends HTTP messages to a service from a BizTalk message. The receive location receives messages from a RESTful service. For GET and DELETE request, the adapter does not use any payload. For POST and PUT request, the adapter uses the BizTalk message body part to the HTTP content/payload.
The WCF-WSHttp is expecting a SOAP envelope and XML see What Is the WCF-WSHttp Adapter? (Microsof.com).
The WCF-WSHttp adapter provides full access to the SOAP security, reliability, and transaction feature

WCF web service call time out

I am consuming a web service from a url. When I test using SoapUI, I get the response immediately (See image below) and that the request data I sent out made it through to the other end.
So in my C# application I did the same thing, I consumed the web service wsdl and auto generated the proxy class. I create a request based on that proxy class with the exact same request data I used in SoapUI and sent out. I confirmed that at the other end they received my data successfully and no error is shown.
However, I never receive any ID back and after a while I would get this exception:
Error The HTTP request to 'http://someURLWebservice.com/WSoperation' has exceeded the allotted timeout of 00:00:59.9470000. The time allotted to this operation may have been a portion of a longer timeout.
Am I missing something here? I downloaded the WSDL and generated the mock service with SoapUI and if I make a call to that mock web service locally, I would get it right away.the ID back right away.
Here is my code:
string serverURL = Settings.Default.ExtensionServiceURL;
//Get Proxy class client
ext.ExtWSPortTypeClient client = new ext.ExtWSPortTypeClient();
EndpointAddress addr = new EndpointAddress(serverURL);
try
{
client.Endpoint.Address = addr;
Uri site = new Uri(serverURL);
client.Endpoint.ListenUri = site;
ExtensionData eData = new ExtensionData();
client.ChannelFactory.CreateChannel();
Console.WriteLine("Sending Locator Event Request to Web Service");
ext.locatorEventResponse1 resp = await client.locatorEventAsync(eData.GenerateLocatorEventRequest(ev));
}
catch (Exception ex)
{
Console.WriteLine("Error " + ex.Message);
}
finally
{
if (client != null)
{
((ICommunicationObject)client).Close();
}
}
In a similar situation, I would start with the following:
Test with the WCF Client and capture the trace file:
Configure WCF Tracing for the client
(http://msdn.microsoft.com/en-us/library/ms733025(v=vs.110).aspx)
Send the message via your WCF Client Application
Let the call timeout and save the trace log data
Test with the soapUI client and capture the Http Log
Clear the soapUI http log (one of the tabs along the bottom)
Send the message via the soapUI test request
Save the Http Log
Once you have the trace information for both clients, you should be able to compare the transactions and hopefully determine the source of the issue. In particular, I would suggest confirming the service addresses on both sides and then comparing the SOAP envelope to make sure the WCF bindings are set consistently with the soapUI settings.
In addition, you could also use Fiddler to view the web service communications. The following SO post provides good reference links. Fiddler and Monitoring Web Service Traffic
Hope this helps.
Regards,
So I ended up configure Fiddler2 to sniff my SoapUI request and compare it against my application request. In the the Application request header I saw the following:
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Host: engage.ext-inc.com
Content-Length: 1036
**Expect: 100-continue**
That Expect:100-continue is not in the SoapUI request which successfully sent out and got the response. With this in mind I took the SoapUI request in Fiddler and compose a new one base on it...except I put in Expect:100-continue and guess what, I received no response.
Upon reading about it I came across this link
And voila, upon putting ServicePointManager.Expect100Continue = false; into my code prior making the web service call I get the response back right away.
Check the message quota settings, it might be that your service is sending more than what is configured

.Net 4. View consumed web service headers and body from request and response

We're consuming a web service (web reference, not service reference), and I need a way to output the entire message being sent (including headers) and the message that gets received.
When I add the web reference, the generated base type of the client object to send the messages is System.Web.Services.Protocols.SoapHttpClientProtocol
I send the messages like so:
ApiService api = new ApiService();
// set the certificate and basic http network credentials
var response = api.SendRequest(messageObject);
I'm able to get the body of the request by serializing messageObject, but can't figure out how to get the full message with the headers.
Since I'm using a certificate and basic authentication, tools like Fiddler, etc. aren't getting me what I need, so I believe I have do something programmatically to pull whats sent and whats received prior to being encrypted with ssl.
EDIT
What I want to see if the data being sent and received to another service from within my WCF service.... e.g.:
// this function is within my WCF service
public ResponseModel Auth()
{
// call to another service here... need to trace this
}
If this is for tracing purposes I have had some success using the tracing capabilities of the System.Net libraries, you should be able to enable the tracing through configuration only.
It's described here: How to: Configure Network Tracing
The resulting log file isn't the easiest to follow, but is described here: Interpreting Network Tracing

Client HTTP Handling & ETag

I'm working on a small SilverLight application, which uses the WebClient to request a REST service. According to this:
http://msdn.microsoft.com/en-us/library/dd920295(v=vs.95).aspx
no caching should be in place when using the 'Client HTTP' handling....
The REST service I'm calling use ETag, so with no Caching in place, I would not expect, that a second call to my service, would contain the If-None-Match header ??
Also when the REST service returns '304' (NotModified) I still get some data, indicating that the data is returned from the cache....
The REST service also sets the 'Vary' header to 'Accept' (so that the Accept header, should be taken into account when generating the Cache key), but is doesn't seem like this is working....
So I'm a bit confised, whether the caching is there or not.... seems like it's half-ways there...
Can someone clearify??
TIA
Søren
I would suggest not using ETags on a WCF service. In IIS, the service or the directory containing the service needs to include an HTTP response header setting the content to expire immediately so that there is no possibility of caching on the client. This way a call to the service will not result in an HTTP 304 response from the server.

WCF REST client with TransferMode=Streamed - logging entire ("raw") http requests/responses

This is on .Net 4, full framework.
I'm trying to make a simple winforms app that will make some simple WCF REST calls. It's using ChannelFactory and the service contract interface. Of the ~20 methods in the interface, 2 of them involve Stream (an upload and a download method) so the service side (and currently also the client side) using TransferMode=Streamed.
My goal is to include the full HTTP request and response (much like you would see in ethereal/wireshark, or fiddler, or whatever), with headers, in a textbox of the winforms app (just to show what went over the wire)
In trying to use the built-in diagnostics (via SvcConfigEditor) and my own (via implementing IClientMessageInspector and then IEndpointBehavior to add the inspector, then channelFactory.Endpoint.Behaviors.Add to add the behavior :), I'm having 2 issues:
When doing request.ToString() or reply.ToString() in BeforeSendRequest and AfterReceiveReply, it only gets the 'body' and not the headers. Digging around in the objects in the debugger it looks like the reply has them in reply.Properties["httpResponse"], but the request's request.Properties["httpRequest"] has an empty Headers property even though Fiddler shows headers for Content-Type, Host, Accept-Encoding, and Connection. It seems like there's likely a better way to get the 'raw' message that I'm missing (and if there's not, someone probably knows an existing chunk of code to 'reconstruct' the raw one from the Message)
Since the transfer mode is Streamed, the 'body' part just shows up as the string '... stream ...', both in SvcTraceViewer (and the 'raw' svclog - even with logEntireMessage=true) and when doing a ToString(). If the mode is Buffered instead, it shows the actual body fine. I tried making a copy with reply.CreateBufferedCopy(int.MaxValue); but that then caused the actual WCF call to fail with an InvalidOperationException: This message cannot support the operation because it has been copied.
One fallback would be to move the client to Buffered and just change to StreamedRequest for the one upload call and StreamedResponse for the download call (but I'd have to do that programmatically AFAICT, as it's set at the binding level in the config and I don't see anyway of doing it via attributes on the calls), which would take care of the 'body' part and leave me with just the "get the http request headers" (issue #1, specifically request.Properties["httpRequest"].Headers being empty) to deal with, but I'm hoping there's some way of logging the 'raw' messages without doing so, leaving the TransferMode as Streamed.
Thanks!
I can't find any reference right now, but it's a known fact that you cannot capture the contents of a streamed message to WCF tracing. When streaming is enabled, only the headers of the message will be traced.
Here's the source: Configuring Message Logging on MSDN
See towards the end of the page:
Service Level
Messages logged at this layer are
about to enter (on receiving) or leave
(on sending) user code. If filters
have been defined, only messages that
match the filters are logged.
Otherwise, all messages at the service
level are logged. Infrastructure
messages (transactions, peer channel,
and security) are also logged at this
level, except for Reliable Messaging
messages. On streamed messages, only
the headers are logged. In addition,
secure messages are logged decrypted
at this level.

Categories