1

I'm trying to update one metadata field - "myToAddress". There are others, but one is good for now. I keep getting "400 bad request". Quite certain the RequestDigest is ok, since I'm able to upload a document.

Here's the code:

public static void UpdateMetaData()
    {
        var uri = new Uri(https://example.com/sites/docs/_api/web/GetFileByServerRelativeUrl('/sites/docs/Email/TestFolder/testMail.msg')"
        var request = WebRequest.Create(uri) as HttpWebRequest;
        request.Credentials = new NetworkCredential(""xxx", "yyy", "zzz");
        request.Method = "POST";
        request.Accept = "application/json; odata=verbose";
        request.ContentType = "application/json; odata=verbose";
        request.Headers.Add("X-HTTP-Method", "MERGE");
        request.Headers.Add("IF-MATCH", "*");
        request.Headers.Add("X-RequestDigest", GetFormDigest());

        string stringData =   "{'__metadata': { 'type': 'SP.File'},'ListItemAllFields': {'__metadata': { 'type': 'SP.Data.EmailItem'}, 'myToAddress': '[email protected]'}}";
        request.ContentLength = stringData.Length;

        StreamWriter writer = new StreamWriter(request.GetRequestStream());
        writer.Write(stringData);
        writer.Flush();

        using (var response = (HttpWebResponse)request.GetResponse())
        {
            using (var reader = new StreamReader(response.GetResponseStream()))
            {
                reader.ReadToEnd();
            }
        }
    }

}

Is stringData formed correctly? I suspect that's the problem - but i don't know how to fix it. Maybe you have to include all of the metadata fields in stringData - not just the one you want to update. It looks like all fields are included in this javascript example: SharePoint 2013 REST api to update list item- Uncaught ReferenceError: etag is not defined

Can you perform an "update" using GetFileByServerRelativeURL?

Is the uri formed correctly? (Do i need change the uri to 'select' or 'expand' fields.)

To see the shape of the metadata i used this "Get" request URI for the document:

    var uri = new Uri(https://example.com/sites/docs/_api/web/GetFileByServerRelativeUrl('/sites/docs/Email/TestFolder/TestMail.msg')?$expand=ListItemAllFields&$select=ListItemAllFields/myToAddress";

The json string per the "Get" request on the document looks like this:

{"d":{"__metadata":            {"id":"Web/GetFileByServerRelativeUrl('/sites/docs/Email/TestFolder/testMail.msg')","uri":"https://example.com/sites/docs/_api/Web/GetFileByServerRelativeUrl('/sites/docs/Email/TestFolder/testMail.msg')","type":"SP.File"},"ListItemAllFields":{"__metadata":{"id":"Web/GetFileByServerRelativeUrl('/sites/docs/Email/TestFolder/testMail.msg')/ListItemAllFields","uri":"https://example.com/sites/docs/_api/Web/GetFileByServerRelativeUrl('/sites/docs/Email/TestFolder/testMail.msg')/ListItemAllFields","etag":"\"1\"","type":"SP.Data.EmailItem"},"myToAddress":null}}}

I'm using code almost exactly like the code in UpdateListItem here: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/40833576-5853-4ca4-95cf-b5b1d69f465f/sharepoint-rest-and-c-sample-to-update-list-item?forum=sharepointdevelopment. But something's not working for me.

1

2 Answers 2

4

Basically this error occurs since endpoint /_api/web/GetFileByServerRelativeUrl('<file url>') could not be used for updating document metadata (or list item associated with a file)

Instead you could utilize /_api/web/GetFileByServerRelativeUrl('<file url>')/ListItemAllFields endpoint for that purpose, for example:

Uri: /_api/web/GetFileByServerRelativeUrl('<file url>')/ListItemAllFields
Method: POST
body: { '__metadata': { 'type': 'SP.Data.DocumentsItem' }, 'Note': 'Content goes here' }
Headers: 
    X-RequestDigest: form digest value
    IF-MATCH": etag or "*"
    X-HTTP-Method: MERGE,
    accept: "application/json;odata=verbose"
    content-type: "application/json;odata=verbose"

Example

var fileUrl = "/Documents/User Guide.docx";
using (var client = new SPWebClient(webUri.ToString()))
{
       client.Credentials = GetCredentials(webUri, userName, password);

       var requestUrl = string.Format("/_api/web/GetFileByServerRelativeUrl('{0}')/ListItemAllFields", fileUrl);
       var payload = new JObject
       {
                ["Notes"] = "Some comments goes here",
                ["__metadata"] = new JObject {["type"] = "SP.Data.DocumentsItem" }
       };
       var updateHeaders = new Dictionary<string,string>();
       updateHeaders["X-HTTP-Method"] = "MERGE";
       updateHeaders["If-Match"] = "*";
       client.ExecuteJsonWithDigest(requestUrl, "POST", updateHeaders, payload);
}

Dependencies

SPWebClient.cs - a WebClient class with a SharePoint specific methods.

0

@Vadim

you can add this method as well to you SPWebClient then you don't have to know SP.Data.DocumentsItem to make it more dynamic

public string GetItemTypeForListName(string listTitle)
        {
            StreamReader reader;

            var url = WebUri + $"/_api/web/lists/getbytitle('{listTitle}')/?$select=ListItemEntityTypeFullName";
            var endpointUri = new Uri(url);

            Stream stream = _client.OpenRead(endpointUri);
            reader = new StreamReader(stream);
            var result = reader.ReadToEnd();
            JToken t = JToken.Parse(result);

            return t["d"]["ListItemEntityTypeFullName"].ToString();

        }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.