Access Denied on Web Service Calls

This question has been asked of me enough that I feel it's worth a blog.  It's not the this solution is unique, but I'm hoping that Google will do its thing with respect to getting the word out to people who need it.

First of all, the symptom we're addressing is an HTTP status code of 401 (Access denied) that is returned when making a call to a web service method through a proxy class. The solution is quite simple.  Actually, to be more precise, there are two solutions, with the best one depending (of course) on your goals. First, the virtual directory in which the web service is running can be modified to allow anonymous access.  Alternatively, the credentials associated with the current user can be attached to the web service call by including the following statement prior to the method call.

ws.Credentials = System.Net.CredentialCache.DefaultCredentials;

Now that the solution has been addressed, let's take a brief look at why the problem exists in the first place.  When a request is made from a browser to a web server, the server may require some form of authentication. It is possible that the initial request can include the authentication information, but if the server doesn't see it, then an HTTP 401 status code is returned.  Included in the response is an Authenticate header which indicates the type of authencation that is expected and the name of the realm being accessed.  The browser then reissues the request, providing an Authentication header including your current credentials.  If that request fails (returns another 401 status), the browser prompts you for a set of credentials.  This is a sequence of events that all of you have seen before, even if the underlying rationale is new information.

However, when you make a web method call through the proxy class, the handshaking that goes on with respect to authentication doesn't take place. It's the browser that does this magic and the proxy class doesn't include that code. The result is that the client application receives the access denied status. So you need to configure the virtual directory to not reject unauthenticated requests (by turning anonymous access on) or provide your own set of credentials with the call (by populating the Credentials property on the proxy class).