1

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.

  • You could just get the userid from the email address and then use the userid. sharepoint.stackexchange.com/questions/133260/… If you structure it correctly it should make little difference to performance unless you're creating a very large number of users. – J. Doe Jan 26 '18 at 11:07
  • Short answer is no, but there might be a better way to get the user IDs than all at once. Can you provide more detail on your use case? If this is from a user form, for example, you can resolve each user ID and store those in your form as each user is entered, then you already have all the user IDs needed to save your user field when ready to commit the change. – Chris Romp Jan 26 '18 at 17:23
  • @ChrisRomp in my scenario user will select multiple people (suppose 10-12 ) from client peoplepicker(office fabric Component) where i am getting user email, display text and remaining properties but userid is not available. I am following the same on user selection callback getting the userid and saving the form is there any way to save data using emails instead of Userid – vamsi krishna Jan 27 '18 at 9:46
  • @vamsikrishna Can you clarify further? The Fabric picker doesn't contain any code for resolving users (developer.microsoft.com/en-us/fabric#/components/peoplepicker). If you're using this, and you're implementing your own search/resolve logic, I have some code I can share that will help. If you're using the ClientPeoplePicker library, which is more "standard" SharePoint, and I believe you're right it doesn't include the SP UserID. – Chris Romp Jan 27 '18 at 17:28
  • @ChrisRomp yes i am using Fabric Picker and i am using '/_api/SP.UI.ApplicationPages.ClientPeoplePickerWebServiceInterface.ClientPeoplePickerSearchUser' API endpoint to search users and getting the data. Can you share the Code which you mentioned so that it can save some of my time. – vamsi krishna Jan 28 '18 at 9:37
1

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. :)

  • i am following the same for searching user and i made some changes as per my requirement like Removing Duplicates (not showing selected user in the suggestions) from search query and if user deletes people from picker deleting user from the saved list. Again thanks for your Help – vamsi krishna Jan 31 '18 at 11:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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