Koen H
Koen H

Reputation: 111

401 Unauthorized on SECOND HttpClient/HttpWebRequest call

I have a application that uses the SharePoint 2010 REST API. In the process of creating an Item there are multiple request done after each other:

1 Call: Getting Items from List: Succes

2 Call: Create Item: 401 Unauthorized

This is the same if I do it like this:

1 Call: Create Item: Succes

2 Call: Delete Item: 401 Unauthorized

What I know is that my functions work separately they DON'T work when they are called after each other. When I close the application (Windows Phone 8.1 app) after creating a item and when restarted try to delete the item it works.

First I thought it had to do with the way I handle my fields so I changed them to NULL in a finally statement but that didn't work.

    public async Task<bool> CreateNewItem(NewItem myNewItem)
    {   
        try
        {
            StatusBar statusBar = await MyStatusBar.ShowStatusBar("Creating new List Item.");
            //Retrieving Settings from Saved file
            mySettings = await MyCredentials.GetMySettings();
            myCred = new NetworkCredential(mySettings.UserName, mySettings.Password, mySettings.Domain);

            using (var handler = new HttpClientHandler { Credentials = myCred })
            {
                HttpClient client = new HttpClient(handler);
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                NewItem newItem = myNewItem;
                var jsonObject = JsonConvert.SerializeObject(newItem);

                HttpResponseMessage response = await client.PostAsync(new Uri(baseUrl + listNameHourRegistration), new StringContent(jsonObject.ToString(), Encoding.Unicode, "application/json"));
                response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                response.EnsureSuccessStatusCode();

                string responseMessage = await response.Content.ReadAsStringAsync();

                client.Dispose();

                if (responseMessage.Length > 0)
                     return true;
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
            return false;
        }
        finally
        {
            request = null;
            response = null;
            myCred = null;
            mySettings = null;
        }
        
        return false;
    }

Upvotes: 2

Views: 5046

Answers (5)

Carlo Bos
Carlo Bos

Reputation: 3293

On a windows machine you can resolve this with this registry setting change:

Go to the following Registry entry:

Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa

Now add a new DWORD to the Lsa folder called: DisableLoopBackCheck and set this to 1

Upvotes: 1

Brandon Duncan
Brandon Duncan

Reputation: 11

I was running into this same error when I realized I was adding the headers each time I was calling the endpoint. Hopefully this will help someone.

Instead I initialized the HttpClient instance in my class constructor and set the headers there. Also I learned it is better practice to only use 1 instance instead of recreating with "using" (See this article https://www.aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/)

I'm invoking CallApiAsync from another class in a loop.

Here's my final solution:

class ApiShared
    {
        private HttpClient client;

        public ApiShared()  {
            client = new HttpClient();
            client.DefaultRequestHeaders.Add("x-api-key", ConfigurationManager.AppSettings["ApiKey"]);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        }

        public async Task<ApiResponse_Root> CallApiAsync(string endpoint)
        {
            // Make API call
            Uri endpointUri = new Uri(endpoint);
            var stringTask = client.GetStringAsync(endpointUri);
            var data = JsonConvert.DeserializeObject<ApiResponse_Root>(await stringTask);

            return data;
        }
    }

Upvotes: 1

Ramalingam S
Ramalingam S

Reputation: 1

I see that this question has been posted long back. But I don't see a correctly working solution posted yet to this thread.

I faced exactly the same issue where the next requests kept on failing returning me 401 UnAuthorized.

I figured out using fiddler that from SECOND request onwards, there was a Cookie added to the request which was possibly a result of Set-Cookie response sent by the server along with first response.

So here's how I tackled the situation - Make UseCookies false:

new HttpClientHandler { Credentials = myCred, UseCookies = false }

This should resolve your issue. Hope this helps someone who's looking for a solution to a similar issue.

Upvotes: -1

Daniel Sklenitzka
Daniel Sklenitzka

Reputation: 2236

While I still don't know what the actual problem is, at least I found a workaround: Use the WebRequest class instead of HttpClient.

Upvotes: 1

Yannic DoNot Text
Yannic DoNot Text

Reputation: 63

Just run into the same problem.

Anyway, the 2nd request does not follow the same authentication procedure. Even if you initialize a new HttpClient object. I sniffed the HTTP traffic. traffic

After the 1st request I am doing another with different credentials. This is also ending in a 401. I am really confused...

Seems the NTLM Handshake stucks at the 2nd of 6 steps http://www.innovation.ch/personal/ronald/ntlm.html

Edit: You may want to use the CSOM. http://social.msdn.microsoft.com/Forums/office/en-US/efd12f11-cdb3-4b28-a9e0-32bfab71a419/windows-phone-81-sdk-for-sharepoint-csom?forum=sharepointdevelopment

Upvotes: 2

Related Questions