2

How to get a CSOM Principal from a user or group ID?

For example to assign permissions stored in a "People" field (which can also contain groups).

At the moment I have this super kludge using ExceptionHandlingScope.

void AddRole(SecurableObject securable, int principalId, RoleDefinition role)
{
    var scope = new ExceptionHandlingScope(context);
    using (scope.StartScope())
    {
        using (scope.StartTry())
        {
            var principal = context.Web.SiteUsers.GetById(principalId);
            securable.RoleAssignments.Add(principal, new RoleDefinitionBindingCollection(context) { role });
        }
        using (scope.StartCatch())
        {
            var principal = context.Web.SiteGroups.GetById(principalId);
            securable.RoleAssignments.Add(principal, new RoleDefinitionBindingCollection(context) { role });
        }
    }
}

The REST API just accepts raw principal ID, but that loses a lot of the advantages of using the CSOM.

0

1 Answer 1

1

You can use the ResolvePrincipal method in the Microsoft.SharePoint.Client.Utilities namespace.

It accepts the principal ID, but you need to send it as string instead of int. Also, instead of ID, if you directly want to send the user's or group's name, it would work

It would work as below:

using Microsoft.SharePoint.Client;    
using Microsoft.SharePoint.Client.Utilities;

void AddRole(SecurableObject securable, int principalId, RoleDefinition role)
{       
    var info = Utility.ResolvePrincipal(context, context.Web, principalId.ToString(), PrincipalType.All, PrincipalSource.All, null, false);

    context.ExecuteQuery();

    Principal principal = null;

    if (info.Value.PrincipalType == PrincipalType.User)
    {
        principal = context.Web.SiteUsers.GetById(principalId);
    }
    else if (info.Value.PrincipalType == PrincipalType.SharePointGroup
          || info.Value.PrincipalType == PrincipalType.SecurityGroup)
    {
        principal = Context.Web.SiteGroups.GetById(info.Value.PrincipalId);
    }
    else
    {
        throw new NotImplementedException($"PrincipalType {info.Value.PrincipalType}");
    }

    securable.RoleAssignments.Add(result, new RoleDefinitionBindingCollection(context) { role });
}

Modified from here - ResolvePrincipal vs SearchPrincipal

2
  • that's interesting to know, but unfortunately requires an additional ExecuteQuery call.
    – Fowl
    Apr 22, 2020 at 8:02
  • ps. I briefly tried this code and for some reason it returned a completely different principal. eg. resolve "10" and returns principal id "135". Haven't had a chance to troubleshoot.
    – Fowl
    Apr 29, 2020 at 7:00

Your Answer

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

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