Wednesday, March 17, 2004

Horrible, Horrible WebService Proxies

[Update: Ivan helped me find a partial workaround. Details here.]

I knew that my implementation of FwSync (my tool for uploading/downloading files from a FlexWiki instance for offline editing) was a little slow sometimes. I figured it was because the web service interface is a little chatty - it requires a roundtrip for every file I'm submitting or retrieving. Boy, did I not know the half of it.

I whipped out a packet sniffer and took a look at what was going across the wire. Imagine my surprise when I discovered that every request to the webserver was turning into three request-response network roundtrips. Ouch! A little more digging, and I found out that I was far from the first one to have this problem - it turns out to be a consequence of the fact that I have Integrated authentication turned on on the webserver, so I have to make one roundtrip to find out that authentication is required, another to get the challenge from the webserver, and a third to actually make an authenticated request. Because the autogenerated web service proxies (the ones you get when you say “Add Web Reference” don't hold on to connections, this process is repeated for every single method call.

At first, I didn't think this was so bad. That's because I knew there was a PreAuthenticate property on the proxy that supposedly told the proxy to send the credentials with the first request, rather than waiting for the “access denied” message to come back. I'd still have a second roundtrip for the challenge-response, but I figured I could optimize that away using the CredentialCache somehow.

Wrong! Oh so freaking wrong!

As it turns out, the autogenerated proxies are busted in a whole bunch of ways. Jon Flanders set me straight on that count - there is no way to get the proxies to preauthenticate when using Integrated authentication. To even get it to work with Basic authentication, you have to follow the instructions here...but forget about Integrated. Lame!

If someone knows of an easy way to get this to work (without having to muck with the server, although I might do that too), I'd love to hear about it.



  1. For integrated authentication, you can improve the performance of calls after the first one by turning on UnsafeAuthenticatedConnectionSharing as well as PreAuthenticate.

  2. Dude, you rock. That little tweak majorly improved performance on the wire. I didn't even have to add PreAuthenticate to cover the Integrated scenario.

  3. I'm not sure PreAuthenticate is even supported with NTLM anyway, due to the challenge/response nature of the protocol. I seem to remember reading somewhere PreAuth only really works with Basic auth (or other protocols where you can know what to send before doing any handshaking).

    Just my two bits.

  4. Right. And I could accept that. The problem is that it doesn't work *at all* in the code that gets generated - not for Basic, not for Integrated, not for nothing. :p

  5. I'm doing a research about the network performance of WSE2, WS, and XMLsocket.

    Could you suggest me some good sniffer to rebuild and analalyze webservices transactions please?



  6. I don't think I'd use a sniffer to do performance analysis...that's not really what they're for.

    If you're looking for a sniffer/analysis package, SOAPScope is really good. Ethereal is a good general-purpose sniffer.

  7. That article about getting PreAuthenticate to work with Basic auth was written in 2002. Are you sure this wasn't fixed in 2003 with .NET 1.1?

  8. Not sure - haven't tried it recently. Are you seeing something different under 1.1/2.0?

  9. Hi guys,

    I know this is terribly late, but I posted a detailed reply to a question on the forums that cited this article so I thought I'd post a link to it here as well in case people find it useful:

  10. I'm using ASP.NET 2.0 and this is still an issue. Despite having PreAuthenticate set to true, my basic auth details are not sent on the first request.

    This is actually winding up being a substantial problem for us, because it means that we wanted to have web services available anonymously, that you could pass authentication credentials to via HTTP Basic. But since authentication is not *required*, IIS will never challenge for auth data. That means that it's *impossible* for us to submit credentials.

    We may have to use SOAP Header authentication instead.