views:

278

answers:

7

I have a WCF client (running on Win7) pointing to a WebSphere service.

All is good from a test harness (a little test fixture outside my web app) but when my calls to the service originate from my web project one of the calls (and only that one) is extremely slow to deserialize (it takes minutes VS seconds) and not just the first time.

I can see from fiddler that the response comes back quickly but then the WCF client hangs on the response itself for more than a minute before the next line of code is hit by the debugger, almost if the client was having trouble deserializing. This happens only if in the response I have a given pdf string (the operation generates a pdf), base64 encoded chunked. If for example the service raises a fault (thus the pdf string is not there) then the response is deserialized immediately.

Again, If I send the exact same envelope through Soap-UI or from outside the web project all is good.

I am at loss - What should I be looking for and is there some config setting that might do the trick?

Any help appreciated!

EDIT:

I coded a stub against the same service contract. Using the exact same basicHttpBinding and returning the exact same pdf string there is no delay registered. I think this rules out the string and the binding as a possible cause. What's left?

+1  A: 

I have had this bite me many times. Check in your WCF client configuration that you are not trying to use the windows web proxy, that step to check on the proxy (even if there is not one configured) will eat up a lot of time during your connection.

Scott Chamberlain
thx! how do I do that - is there any specific setting I need to check?
JohnIdol
useDefaultWebProxy="false" is no good - still happening - any other suggestion?
JohnIdol
Sorry, when I changed mine from true to false it got rid of my speed issue.
Scott Chamberlain
A: 

First things to check:

  • Is the config the same in the web project and the test project?
  • When you test from SOAP UI are you doing it from the same server and in the same security context as when the code is running from the web project. -Is there any spike in the memory when the pdf comes back?

Edit

From your comments the 1 min wait, appears that it is waiting for a timeout. You also mention transactions.

I am wondering if the problem is somewhere else. The call to the WCF service goes OK, but the call is inside a transaction, and there is no complete or dispose on the transaction (I am guessing here), then the transaction / code will hang for 1 min while it waits to timeout.

Edit 2

Next things to check:

  • Is there any difference in the code is the test and in the web project, on how the service is being called.
  • Is there any differnce in the framework version, for example is one 3.0 and the other 3.5
Shiraz Bhaiji
thx - binding + endpoint are the exact same, and the service reference is also the exact same. I am doing all the tests from the same machine in the same context. The only difference us that this only happens in the web proj. Did not check memory - will try that and look for spikes.
JohnIdol
one interesting thing is that even though I see the response coming back immediately with fiddler the WCF trace logs the request/response pair after the deserialization is done - after 1 minute (and it shows the the transaction took more than 1 minute to complete)
JohnIdol
sorry for the confusion - there are no such transactions involved. By transaction I meant the request/response pair. As of now I think the problem lies in the fact the the pdf string is base64 encoded.
JohnIdol
see my last edit to the question - I think the encoding of the string can be ruled out (and indeed didn't make sense as the cause)
JohnIdol
no difference in how the service is being called (goes through the exact same service reference) - framework version is the exact saem in fact the tests and the web project are in the same solution
JohnIdol
A: 

If the tips of the other users don't help, you might want to Enable WCF Tracing and open it in the Service Trace Viewer. The information is detailed, but it has enabled me to fix a number of hard-to-identity problems in the past.

More information on WCF Tracing can be found on MSDN.

Richard Szalay
I have that hooked up but could not spot anything strange. It'd be easier if I had a clue what to look for.
JohnIdol
If the log file is small enough, try adding it to your question test. If not, you can send it to me at [email protected] (with my actual name, obviously) and I'll take a look.
Richard Szalay
A: 

Can it be that client side is trying to analyse what type of content is coming from server side? Try to specify mime type of the service response explicitly on the server side, e.g. Response.ContentType = "application/pdf" EDIT: By client side I mean any possible mediator like a firewall or a security suite.

SlavaGu
thx, but the "hanging" happens way before it doesn't even get to that (btw the content type is already specified as u suggest)
JohnIdol
+1  A: 

Two thing you can try:

  1. Adjust the readerQoutas settings for your client. See http://msdn.microsoft.com/en-us/library/ms731325.aspx

  2. Disable "Just My Code" in debugging options. Tools -> Options -> Debugging -> General "Enable Just My Code (Managed only)" and see if you can catch interal WCF exceptions.

//huusom

Huusom
already tried to catch all exceptions and no luck - also tried to max out all the reader quotas and no luck either! :(
JohnIdol
this is getting more and more fun :) Is it possible that we could see configuration for the client and service specification?
Huusom
found the problem! see my own answer - I like you answer though, so +1
JohnIdol
+2  A: 

Changing transferMode="Buffered" into transferMode="Streamed" on the binding did the trick!

So the payload was apparently being chunked in small bits the size of the buffer.

I thought the same could have been achieved by increasing the buffersize (maxBufferSize="1000000") but I had that in place already and it did not help.

JohnIdol
+1  A: 

I had the very same issue... The problem of WCF, IMO, is in the deserialization of the base64 string returned by the service into a byte[] client side.

The easiest to solve this if you may not change your service configuration (Ex.: use a transferMode="Streamed") is to adapt your DataContract/ServiceContract client side. Replace the type "byte[]" with "string" in the Response DataContract.

Next simply decode the returned string yourself with a piece of code such as:

byte[] file = Convert.FromBase64String(pdfBase64String);

To download a PDF of 70KB, it used to required ~6 sec. With the suggested change here above, it takes now < 1 sec.

V.

PS.: Regarding the transfer mode, I did try to only change the client side (transferMode="StreamedResponse") but without improvement...

interesting, thx - I solved by setting transferMode="Streamed"on the client, as that's the only thing I had access to
JohnIdol