Search code examples
.netasp.netweb-serviceshttp-status-codes

What causes "HTTP status 401: OK"


I have an ASP.NET Web Service, when I call it occasionally it returns the correct response, other times it is returning the exception The request failed with HTTP status 401: OK. Can someone please provide me with some reasons why this would be occurring? As I can't seem to find anything on HTTP 401 and a message of OK since 200 is OK and 401 is Unauthorized... Why would my Web Service hosted in IIS6 be returning this?

Here's the direct exception details:

Message:
    The request failed with HTTP status 401: OK.
Stack Trace:
    at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
    at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
    at ws.Main.MethodName(param1, param2)

I will be trying to get a WireShark packet trace for this error when I am provided with it.

Both the client and the Web Service are code that we maintain. The exception only occurs intermittently and not always, the credential details passed through are valid AD user details for an account and IIS site is using Windows Authentication.


Solution

  • I have found the cause and have an answer.

    The problem was caused by multiple threads accessing the WebService at the same time over the same TCP pipe. This caused IIS to reset the authentication handshake and as a result the application received HTTP 401 UNAUTHORIZED exceptions in place of the 200 OK message, .NET was reporting the response was HTTP 401 OK, however using WireShark I was able to determine that the content was still HTTP 401 UNAUTHORIZED.

    Due to the multi-threaded nature of the problem we had it occur very intermittently.

    Solution was to write a new proxy class that encompass our auto-generated ws proxy class (from the WSDL) and implementing a SYNCLOCK object over every method within this new proxy class.

    The problem also seemed to go away when I was using the server name rather than a DNS name because each separate thread call went on a different TCP pipe.