Reputation: 33
I have a C# console application (which will ultimately be a windows service when it's finished). The purpose is to migrate a document store (500k+ documents) over to SharePoint 2013.
Note, this is a standalone C# app that will run on a server that does not have SharePoint installed. I am using pure REST via HttpClient calls.
Uploading a document and setting its metadata has 3 steps:
Upload the document (POST)
e.g. baseURL + "web/" + "GetFolderByServerRelativeUrl('/sites" + libPath + "')/Files/Add(url='" + filename + "',overwrite=true)";
Retrieve details for the list item associated with this document (GET)
e.g. baseURL + "web/lists/getbytitle('" + docLibName + "')/items?$filter=Title eq '" + filenameNoExt + "'"
These first 2 steps are working fine.
This is the bit that's causing me sleepless nights now. I can't seem to figure out what exactly I should be sending to the web service, and anything I try just gives errors. I can't find any examples of anyone who's tried to do this; and the MS documentation is very sparse.
The MS documentation from http://msdn.microsoft.com/en-us/library/office/dn292552%28v=office.15%29.aspx says:
The following example shows how to update a list by using the MERGE method.
url: http: //siteurl/_api/web/lists(guid'list GUID')
method: POST
body: { '__metadata': { 'type': 'SP.List' }, 'Title': 'New title' }
Headers:
Authorization: "Bearer " + accessToken
X-RequestDigest: form digest value
IF-MATCH": etag or "*"
X-HTTP-Method: MERGE,
accept: "application/json;odata=verbose"
content-type: "application/json;odata=verbose"
content-length:length of post body
In my application, I have set the type in the query to SP.Data.CertificatesItem, which is what was returned in step 2; and I'm trying to set the Certificate Type field to the specified value, rather than the document title:
string body = "{ '__metadata': { 'type': '" + spItemType + "' }, 'CertificateType': 'Medical Certificate'}";
(there are several fields which need to be set; I am just hard-coding one field here for testing purposes. The fields which need to be set depend on the content type of the document library.)
Additionally, the URL is slightly different. Where the example had:
http: //siteurl/_api/web/lists(guid'list GUID')
I have (specific example, slightly anonymized):
http: //siteurl/_api/Web/Lists(guid'cdcbef76-8bc0-4a68-9279-f6f3b6cbd3c3')/Items(2)
Otherwise, my call is identical to the example above.
I am getting the error message:
{"error":{"code":"-1, Microsoft.SharePoint.Client.InvalidClientQueryException","message":{"lang":"en-US","value":"The parameter __metadata does not exist in method GetById."}}}
I don't understand what I'm doing wrong! And I can't find any concrete examples anywhere.
From the page: http://msdn.microsoft.com/en-us/library/office/dn292553%28v=office.15%29.aspx :
If you want to update a file's metadata, you'll have to construct an endpoint that reaches the file as a list item. You can do this because each folder is also a list, and each file is also a list item. Construct an endpoint that looks like this: https: //siteurl/_api/web/lists/getbytitle('Documents')/items(). Working with lists and list items with REST explains how to update a list item's metadata.
Can anyone provide any insight here?
UPDATE:
Seems the X-HTTP-Method wasn't getting set correctly. I fixed that, now I'm getting:
{"error":{"code":"-1, Microsoft.SharePoint.Client.InvalidClientQueryException","message":{"lang":"en-US","value":"An unexpected 'PrimitiveValue' node was found when reading from the JSON reader. A 'StartObject' node was expected."}}}
Upvotes: 1
Views: 6480
Reputation: 710
I came across your question while looking into this myself. I have documented how to do file uploads, creating, updating and retrieving list items including those with Termstore data all in .NET using the HttpClient with no JQuery required.
Example for updating a file from the HttpClient using REST:
client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });
client.BaseAddress = new System.Uri(url);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("X-RequestDigest", digest);
client.DefaultRequestHeaders.Add("X-HTTP-Method", "MERGE");
client.DefaultRequestHeaders.Add("IF-MATCH", "*");
HttpContent strContent = new StringContent(String.Concat("{ '__metadata': { 'type': 'SP.List' }, 'Title': '", filename, "' }"));
strContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
strContent.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("odata", "verbose"));
HttpResponseMessage updateResponse = await client.PostAsync(String.Concat("_api/web/lists/GetByTitle('Project Photos')/Items(", id, ")"), strContent);
updateResponse.EnsureSuccessStatusCode();
if (updateResponse.IsSuccessStatusCode)
{}
Hopefully this helps.
Arcan.NET
Upvotes: 0