Question

Below are 2 code snippets used to check if a folder exists in a SharePoint document library. The PROPFIND method seems to work, while the other method, using HEAD results in a 401.

Can someone please tell me why? Don't get distracted by the credentials, I've set it to the same in both examples, and it works fine....

Here is the code that works:

// Create the web request object
var oReq = (HttpWebRequest)WebRequest.Create(url);

// Set the needed properties
oReq.Method = "PROPFIND";
oReq.Credentials = this.wsLists.Credentials; // Use same credentials as wsLists. 
oReq.AllowAutoRedirect = true;
oReq.UserAgent = "Microsoft-WebDAV-MiniRedir/6.1.7600";

// Enumerate through top level only, increasing the depth will find children.
oReq.Headers["Depth"] = "0";
oReq.Headers["translate"] = "f";
var oRequest = new StreamWriter(oReq.GetRequestStream());
oRequest.WriteLine();
oRequest.Close();
var oResponse = new StreamReader(oReq.GetResponse().GetResponseStream());
string sResponse = oResponse.ReadToEnd();
oResponse.Close();

and here is the offending code:

private bool MossResourceExists(string url)
{
    var request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = "HEAD";

    // Create a new CredentialCache object and fill it with the network
    // credentials required to access the server.
    var myCredentialCache = new CredentialCache();
    if (!string.IsNullOrEmpty(this.Domain ))
    {
        myCredentialCache.Add(new Uri(url),
       "NTLM",
       new NetworkCredential(this.Username , this.Password , this.Domain )
       );
    }
    else
    {
        myCredentialCache.Add(new Uri(url),
       "NTLM",
       new NetworkCredential(this.Username , this.Password )
       );
    }

    request.Credentials = myCredentialCache;

    try
    {
        request.GetResponse();
        return true;
    }
    catch (WebException ex)
    {
        var errorResponse = ex.Response as HttpWebResponse;

        if (errorResponse != null)
            if (errorResponse.StatusCode == HttpStatusCode.NotFound)
                return false;
            else
                throw new Exception("Error checking if URL exists:" + url + ";Status Code:" + errorResponse.StatusCode + ";Error Message:" + ex.Message ) ;
    }
    return true;
}
Was it helpful?

Solution

My two cents:

I think it has to do with the way WebDAV works:

  • the first request is always sent anonymous, because WebDAV is a "challenge / response" protocol, That first request without auth headers is necessary; the response from WebDAV contains a nonce to validate the next request, helping deflect against, for example, replay attacks. (from answer to this question, see links in answer for more info).

  • Is the site you are trying to access in your "Local Intranet" zone in IE? If not, the following might give some more info on your issue and a possible woraround:

Understanding Why it Happens

When you use Internet Explorer to access the WebDAV site, Internet Explorer uses Windows HTTP Services (WinHTTP). WinHTTP sends user credentials only in response to requests that occur on a local intranet site during an authenticated logon process. However, WinHTTP does not check the security zone settings in Internet Explorer to determine whether a Web site is a local intranet site. Instead, WinHTTP depends on the proxy settings in Internet Explorer to determine whether a Web site is a local intranet site.

If the Automatically detect settings option is not enabled, any auto-configuration script that is defined will not be processed. WinHTTP will not identify the WebDAV site as a local intranet site. Therefore, WinHTTP will send out a request without user credentials, and you will be prompted to type user credentials.

So as you can see, this problem only seem to appear on an Extranet site and not on an Intranet site. Unfortunately many of my customers run geophysical solutions all over the country with no proxy's in between. From here.

OTHER TIPS

The request did not generate the 401. The 401 came from the server. You should look at the Windows Event Logs, IIS log, and SharePoint logs on the server, to see why the server returned a 401.

I think the response is actually valid, and 401 is OK here. Look, 401 means "unauthorized". So, when you try to access a resource, SharePoint first checks your credentials to see if you are allowed to do it. If you don't have access, it will return 401, if you do, it will return 200+ contents of what you have asked for.

Now, what is the difference between the two:

  • when you are asking for resource you do not have access to
  • when you are asking for resource that does not exist

The basic principle in SharePoint is - if you don't have access to a thing, it DOES NOT EXIST for you and you SHOULDN'T know whether it exists or not.

If SharePoint allowed you to HEAD for a resource you do not have access to, you could try to look for http://sharepointsite/docs/JL_Gets_A_Salary_bonus.doc to see if you have a salary bonus or not.

This is why you get an "access denied" both on resources you don't have access to AND on resources that don't exist.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top