3

I am trying to create an app that will set item level security for certain items in a library. However, I am getting the error mentioned above after these lines:

item.RoleAssignments.Add( grp, roleDefBinding );
ctx.ExecuteQuery();

I found this question on Stack Overflow, and tried to copy the code, with some changes. Here is the full code:

var spContext = SharePointContextProvider.Current.GetSharePointContext( Context );
using ( var ctx = spContext.CreateUserClientContextForSPHost() )
{
    Web w = ctx.Web;
    ctx.Load( w, web=> web.SiteGroups, web=>web.RoleDefinitions );
    ctx.ExecuteQuery();

    List list = w.Lists.GetById( Guid.Parse( ddlLibraries.SelectedItem.Value ) );
    ctx.Load(list);
    ctx.ExecuteQuery();

    String 
        roleNameStr = ddlPermissions.SelectedItem.Text,
        grpName = ddlBUs.SelectedItem.Text;

    var role = w.RoleDefinitions.Where( r => r.Name == roleNameStr );
    if ( role.Count() > 0 )
    {
        RoleDefinition roleDef = role.First();
        var group = w.SiteGroups.Where( g => g.Title == grpName );
        if ( group.Count() > 0 )
        {
            RoleDefinitionBindingCollection roleDefBinding = new RoleDefinitionBindingCollection( ctx );
            ctx.ExecuteQuery();
            roleDefBinding.Add( roleDef );

            Group grp = group.First() as Group;

            CamlQuery query;
            query = CamlQuery.CreateAllItemsQuery();

            Microsoft.SharePoint.Client.ListItemCollection items = list.GetItems( query );
            ctx.Load( items );
            ctx.ExecuteQuery();

            foreach ( Microsoft.SharePoint.Client.ListItem item in items )
            {
                ctx.Load( item, i=>i.RoleAssignments, i=>i.HasUniqueRoleAssignments );
                ctx.ExecuteQuery();
                if ( !item.HasUniqueRoleAssignments )
                {
                    item.BreakRoleInheritance( true, false );
                    ctx.ExecuteQuery();
                }
                item.RoleAssignments.Add( grp, roleDefBinding );
                ctx.ExecuteQuery();
            }
        }
    }
}

Are there any errors in my code, or something I am missing? Not sure if it makes a difference, but this is an Office 365 environment.

Thank you in advance.

4

It might be the ExecuteQuery you call right after you create RoleDefinitionBindingCollection.

This code should work:

static void BreakInheritanceAndSetRoleAssignmentByGroupOnItems(ClientContext clientContext, 
    Web web, string roleName, string groupTitle, List<ListItem> items)
{
    var role = web.RoleDefinitions.FirstOrDefault(r => r.Name == roleName);
    if (role == null) return;

    var group = web.SiteGroups.FirstOrDefault(g => g.Title == groupTitle);
    if (group == null) return;

    var roleDefBinding = new RoleDefinitionBindingCollection(clientContext) {role};

    items.ForEach(item =>
    {
        if (!item.HasUniqueRoleAssignments)
        {
            item.BreakRoleInheritance(true, false);
        }
        item.RoleAssignments.Add(group, roleDefBinding);
    });
}

Note that it does not call ExecuteQuery at all, which is a good thing. But it also expects your Web to contain the correct values, as well as items.
Example usage:

var web = ctx.Web;
var items = web.Lists.GetByTitle("Test").GetItems(CamlQuery.CreateAllItemsQuery());
ctx.Load(items, collection => collection.Include(item => item.HasUniqueRoleAssignments));
ctx.Load(web, w=> w.SiteGroups.Include(sg => sg.Title), w=> w.RoleDefinitions.Include(rd => rd.Name));

ctx.ExecuteQuery();

const string roleName = "Edit"; 
const string groupName = "MyGroup"; 

BreakInheritanceAndSetRoleAssignmentByGroupOnItems(ctx, web, roleName, groupName, items.ToList());
ctx.ExecuteQuery();
  • Note that this will not remove the existing permissions. If you want to do that you could do something like item => item.RoleAssignments when loading items and then calling item.RoleAssignments.ToList().ForEach(ra => ra.DeleteObject()); where you call BreakRoleInheritance – eirikb Apr 30 '14 at 6:07
  • This worked. I'm still new to CSOM, and still a bit confused when to call ClientContext.ExecuteQuery(). Thank you. – wjervis Apr 30 '14 at 11:30

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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