I am trying to create a form for a SharePoint Hosted app that will allow users to request a teamsite. The form writes to a list that is contained in the SharePoint site collection, from which a timer job will read and complete the teamsite provisioning process. The list I am updating contains vital 'User and Group', 'Choice', and 'URL' fields and I am having difficulty getting my REST post to work.
When I run this code, I get a 400 error with this JSON reponse:
{"error":{"code":"-1, Microsoft.SharePoint.Client.InvalidClientQueryException","message":{"lang":"en-US","value":"A 'PrimitiveValue' node with non-null value was found when trying to read the value of a navigation property; however, a 'StartArray' node, a 'StartObject' node, or a 'PrimitiveValue' node with null value was expected."}}} Bad Request
I have not been able to find any examples online of non-text fields being updated via REST services, so if anyone could provide samples or point me to good sources of information I would greatly appreciate it!
function CreateTeamsite() {
var url = _spPageContextInfo.siteAbsoluteUrl;
teamsiteValues = {
//SP.Data.Teamsite_x0020_ListListItem
"__metadata": { "type": "SP.Data.Teamsite_x0020_ListListItem"},
//"__metadata": { "type": "SP.Data." + listName.charAt(0).toUpperCase() + listName.slice(1) + "ListItem" },
"Title": $('input[id=ctl00_PlaceHolderMain_txt_name]').val(),
"BusinessUnit": $("#sel_bu option:selected").text(),
"Description_x002f_Purpose":"test", // $('input[id=ctl00_PlaceHolderMain_txt_purpose]').val(),
"Members": peoplePicker_Members.GetAllUserKeys(),
"SecondaryOwner": peoplePicker_secondaryOwner.GetAllUserKeys(),
"Viewers": peoplePicker_Viewers.GetAllUserKeys(),
"Function": $("#sel_function option:selected").text(),
"SeoKeywords": "test", //$('input[id=ctl00_PlaceHolderMain_txt_keywords]').val(),
"Language1": $('input[id=ctl00_PlaceHolderMain_txt_language]').val(), //need to add this to the form
"PrimaryOwner": peoplePicker_secondaryOwner.GetAllUserKeys(), //TODO: get the logged in user's login id
"TimeZone1": $("#sel_timezone option:selected").val(),
"TypeofTeamsite": $("input[name=type]:checked").val(),
"URL": $('input[id=ctl00_PlaceHolderMain_txt_Url]').val()
};
var outputstring = "Confirm and Submit<br />";
for (var key in teamsiteValues) {
if (teamsiteValues.hasOwnProperty(key)) {
outputstring += key + " -> " + teamsiteValues[key] + '<br />';
}
}
$('#confirm').html(outputstring);
submitTeamsite();
}
function submitTeamsite()
{
var url = _spPageContextInfo.siteAbsoluteUrl;
//var url = "http://teams.cce.com"; //TODO: pull this value from configuration later
$.ajax({
url: url + "/_api/web/lists/getbytitle('" + listName + "')/items",
type: "POST",
contentType: "application/json;odata=verbose",
data: JSON.stringify(teamsiteValues),
headers: {
"Accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: function () { $('#message').text("Teamsite successfully submitted.");
},
error: function (jqXHR, textStatus, errorThrown) { $('#message').text("Update failed." + jqXHR.responseText + " " + errorThrown.toString()) }
});
}
Update: I have found the answer to most of my question. Regarding the URL field, that is passed in a JavaScript object with Description and URL properties.
"URL": {
"Description": $('input[id=ctl00_PlaceHolderMain_txt_Url]').val(),
"Url": "http://teams.cce.com/" + $('input[id=ctl00_PlaceHolderMain_txt_Url]').val()
},
For the Choice field, just pass in the value and that works.
For the "person or group" field, it's not so clear. I get that we need to pass in a numeric id that corresponds to the user. I found that out though looking at the list item XML:
<d:PrimaryOwnerId m:type="Edm.Int32">2</d:PrimaryOwnerId>
I am using a client-side people picker in the form app. Now, how do I get that ID from the people picker so that I can pass it to the REST query?