Reputation: 1005
I am creating a WCF service in which I am executing CRUD operations in sharepoint list. I have retrieved data from sharepoint list successfully via REST i.e. passed credentials (username, password, domain) through network credentials object but unfortunately could not insert data. The error refers to unauthorized access while inserting data in sharepoint. Then I tried Sharepoint online credentials object, but no luck. I need some assistance.
Here is the exception:
The remote server returned an error: (401) Unauthorized.
Here is the code:
try
{
string userPassword = "password";
WebClient webClient = new WebClient();
SecureString securePassword = new SecureString();
for (int i = 0; i < userPassword.Length; i++)
{
securePassword.AppendChar(userPassword[i]);
}
webClient.Credentials = new SharePointOnlineCredentials(@"username@domain", securePassword);
webClient.Headers.Add("Content-type", "application/json");
webClient.Headers.Add("Accept", "application/json;odata=verbose");
webClient.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36");
webClient.Encoding = Encoding.UTF8;
string msg = webClient.UploadString("http://abc:9211/sites/api/_api/web/lists/getbytitle('list_name')/Items", "POST", "{__metadata\":{\"type\":\"SP.Data.SubscriptionListItem\"},\"UserID\":\"user\",\"SubscriptionType\":\"Type1\",\"Title\":\"Testing\"}");
}
catch(WebException ex)
{
}
Upvotes: 4
Views: 6478
Reputation: 59338
This error occurs since for performing Create, Update or Delete operation Request Digest
value have to be specified during request in SharePoint Online/Office 365.
Request Digest
X-RequestDigest
header stores a security validation token that allows to help prevent the type of attack whereby a user is tricked into posting data to the server without knowing it.
using System;
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace SPORestClient
{
/// <summary>
/// Client for performing CRUD operations against List resource in SharePoint Online (SPO)
/// </summary>
public class ListsClient : IDisposable
{
public ListsClient(Uri webUri, ICredentials credentials)
{
_client = new WebClient();
_client.Credentials = credentials;
_client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
_client.Headers.Add(HttpRequestHeader.ContentType, "application/json;odata=verbose");
_client.Headers.Add(HttpRequestHeader.Accept, "application/json;odata=verbose");
WebUri = webUri;
}
public void InsertListItem(string listTitle, object payload)
{
var formDigestValue = RequestFormDigest();
_client.Headers.Add("X-RequestDigest", formDigestValue);
var endpointUri = new Uri(WebUri, string.Format("/_api/web/lists/getbytitle('{0}')/items", listTitle));
var payloadString = JsonConvert.SerializeObject(payload);
_client.Headers.Add(HttpRequestHeader.ContentType, "application/json;odata=verbose");
_client.UploadString(endpointUri, "POST", payloadString);
}
/// <summary>
/// Request Form Digest
/// </summary>
/// <returns></returns>
private string RequestFormDigest()
{
var endpointUri = new Uri(WebUri, "_api/contextinfo");
var result = _client.UploadString(endpointUri, "POST");
JToken t = JToken.Parse(result);
return t["d"]["GetContextWebInformation"]["FormDigestValue"].ToString();
}
public Uri WebUri { get; private set; }
public void Dispose()
{
_client.Dispose();
GC.SuppressFinalize(this);
}
private readonly WebClient _client;
}
}
Gist: [ListsClient.cs][2]
Note: Since SharePoint requires the user to include a request digest value with each create, update and delete operation, an additional request is invoked using
RequestFormDigest method
to request Context Info entity that contains request digest value.
--
Dependency: [Json.NET library][1]
Usage
The following example demonstrates how to create List Item in Contacts
List:
using (var client = new ListsClient(webUri, credentials))
{
var contactEntry = new
{
__metadata = new { type = "SP.Data.ContactsListItem" },
Title = "John Doe"
};
client.InsertListItem("Contacts", contactEntry);
}
Upvotes: 5