Is it possible to Update SharePoint user field in Rest API with Email?
Question
Is it possible to Save/Update User Field in SharePoint Rest API using email Addresses instead of USERID. Because in order to save 20 users i need to make 20 rest calls to get Userid is there any alternative to save users using EMail.
La solution
Based on our Q&A in the comments, here is my recommendation: If you're using the /_api/SP.UI.ApplicationPages.ClientPeoplePickerWebServiceInterface.clientPeoplePickerSearchUser
to search the users, then once your users selects a user, you can resolve it via /_api/SP.UI.ApplicationPages.ClientPeoplePickerWebServiceInterface.clientPeoplePickerResolveUser
(or you can use clientPeoplePickerSearchUser
again -- I don't honestly know the difference and the same approch applies).
I've found some entity types already have the SPUserID
in the EntityData
(external users seem to, at least in my limited testing), but most don't. However, as users select to resolve a found user, check if the ID is there, and if not, immediately call the /_api/web/EnsureUser
method in the background. Store the result Id
into an array, then when you're POSTing to the list web service to create your list item, use that array value.
Example searching:
$.ajax({
'url': _spPageContextInfo.webAbsoluteUrl + '/_api/SP.UI.ApplicationPages.ClientPeoplePickerWebServiceInterface.clientPeoplePickerResolveUser',
'method': 'POST',
'data': JSON.stringify({
'queryParams': {
'__metadata': {
'type': 'SP.UI.ApplicationPages.ClientPeoplePickerQueryParameters'
},
'AllowEmailAddresses': true,
'AllowMultipleEntities': true,
'AllUrlZones': false,
'MaximumEntitySuggestions': 50,
'PrincipalSource': 15,
'PrincipalType': 15,
'QueryString': 'Romp' // <-- Search query from picker control
//'Required':false,
//'SharePointGroupID':null,
//'UrlZone':null,
//'UrlZoneSpecified':false,
//'Web':null,
//'WebApplicationID':null
}
}),
'headers': {
'accept': 'application/json;odata=verbose',
'content-type': 'application/json;odata=verbose',
'X-RequestDigest': $('#__REQUESTDIGEST').val()
},
'success': function(data) {
// TODO: Something to display your results in the picker
console.log(data); var userData = JSON.parse(data.d.ClientPeoplePickerSearchUser);
console.log(userData);
},
'error': function(err) {
console.error(err);
}
});
Example resolving. When the form loads you'll want to create an empty array to store your results in. I'm using resovledIds
here:
var resolvedIds = [];
$.ajax({
'url': _spPageContextInfo.webAbsoluteUrl + '/_api/SP.UI.ApplicationPages.ClientPeoplePickerWebServiceInterface.clientPeoplePickerResolveUser',
'method': 'POST',
'data': JSON.stringify({
'queryParams': {
'__metadata': {
'type': 'SP.UI.ApplicationPages.ClientPeoplePickerQueryParameters'
},
'AllowEmailAddresses': true,
'AllowMultipleEntities': true,
'AllUrlZones': false,
'MaximumEntitySuggestions': 50,
'PrincipalSource': 15,
'PrincipalType': 15,
'QueryString': 'Romp'
}
}),
'headers': {
'accept': 'application/json;odata=verbose',
'content-type': 'application/json;odata=verbose',
'X-RequestDigest': $('#__REQUESTDIGEST').val()
},
'success': function(data) {
var userData = JSON.parse(data.d.ClientPeoplePickerResolveUser);
if (userData.EntityData && userData.EntityData.SPUserID) {
// User ID found
resolvedIds.push(parseInt(userData.EntityData.SPUserID)); // It's a string for some reason, so use parseInt
} else {
// No user ID returned, so we need to call EnsureUser
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/EnsureUser",
type: "POST",
data: "{ 'logonName': '" + userData.Key + "' }", // Uses the key from the previous call
headers: {
"X-RequestDigest": $('#__REQUESTDIGEST').val(),
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose"
},
success: function(data) {
resolvedIds.push(data.d.Id); // Here's our ID
},
error: function(err) {
console.error(err);
}
});
}
},
'error': function(err) {
console.error(err);
}
});
Now that you have your array of user IDs, when you're inserting your list item, you'll pass the array like so (if your user field is called MyUsers
):
MyUsersId: {
'__metadata': {
'type': 'Collection(Edm.Int32)'
},
'results': resolvedUserIds
}
In summary, since you need to get the SharePoint user IDs as integers, if they're not coming back when resolving the looked-up users, then resolve them asynchronously as the users are entering them (they won't notice it happening), rather than trying to resolve 20 users all at once.
This same approach would work even with the classic SPClientPeoplePicker
control, by using the OnUserResolvedClientScript
callback method and calling EnsureUser
at that time, and also persisting its value to an array to use later.
Some other answers suggest using /_vti_bin/ListData.svc/UserInformationList
, but I won't cover that here as I prefer this approach. But feel free to look into that one for an alternate approach.
I hope this answers your question. If not let me know and I'll flesh it out some more. :)