So we’ve been trying to interop with a web service at work that requires Basic authentication. Unfortunately we get one of the following errors (depending on if we’re going via our ISA proxy server or not):
- System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. —> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. —> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
- System.Net.WebException: The request failed with HTTP status 502: Proxy Error ( The specified network name is no longer available. ).
It turns out (thanks to ethereal), that for some reason the .Net Framework is ignoring the ’401 Access Denied’ reply and assuming that the web service is usable. Oddly enough Squid handles the request perfectly, so does just bouncing the request via another box – so there’s clearly something odd going on inside the framework.
So no problem, we’ll just set PreAuthenticate to true. Except that only affects secondary requests:
“With the exception of the first request, the PreAuthenticate property indicates whether to send authentication information with subsequent requests to the specific Uri without waiting to be challenged by the server.”
The solution is rather hackish, but works while we wait for MS to code and test a real solution:
Paste this code into your web service proxy class, or preferably create a new file and extend the partial class. This means your code won’t be erased when the proxy class is recreated when you update the web reference.
protected override WebRequest GetWebRequest(Uri uri)
WebRequest webRequest = base.GetWebRequest(uri);
NetworkCredential credentials = Credentials as NetworkCredential;
if (credentials != null)
string authInfo =
((credentials.Domain != null) && (credentials.Domain.Length > 0) ?
credentials.Domain + @"\" : string.Empty) +
credentials.UserName + ":" + credentials.Password;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
webRequest.Headers["Authorization"] = "Basic " + authInfo;