Using the SharePoint 2010 Client Object Model – Part 5

The previous posts in this series have been pretty list-centric.  In this posting we’re going to delve down a different path in exploring the client object model and talk about security.  The client OM actually provides great support for working with the security model in SharePoint.  You can do everything from getting a list of groups and members to enumerating roles (permissions levels), the rights associated with them, creating new users and groups, breaking inheritance, and more.  Let’s go ahead and start with the most straightforward scenarios and start working our way down the list.

We’ll start out by getting a list of groups in the site:

//get the connection

ClientContext ctx = new ClientContext(“http://foo”);

               

//get the groups

GroupCollection grps = ctx.Web.SiteGroups;

 

//load up the group info

ctx.Load(grps);

//execute the query

ctx.ExecuteQuery();

 

// enumerate

foreach (Group grp in grps)

{

// do something with each group

}

So we’re following the pattern we’ve seen throughout in these posts – getting our connection, creating our query and executing the query.  The SiteGroups property is a simple enumeration that’s easy to work with.    If we wanted to get the members of that group, we could just add this additional code while we enumerate each group:

UserCollection usrs = ctx.Web.SiteGroups.GetById(grp.Id).Users;

ctx.Load(usrs);

ctx.ExecuteQuery();

Side note:  I’ll cover a more efficient way in which to deal with object properties like this below.  Getting the list of permissions levels, also known as RoleDefinitions is equally easy:

RoleDefinitionCollection roleDefs = null;

roleDefs = ctx.Web.RoleDefinitions;

ctx.Load(roleDefs);

And then we call ExecuteQuery and it works just like enumerating the SiteGroups as shown above.   Now, figuring out the rights associated with an individual RoleDefinition is a little different.  Assume that we’re enumerating through the list of RoleDefinitions.  For each one we need to also enumerate through all the possible BasePermissions and call the Has method on the BasePermissions class to see if that BasePermission is part of that RoleDefinition.  The code for doing that would look something like this:

foreach (RoleDefinition rd in roleDefs)

{

      //enumerate the enum and check each permission

//type to see if the perm is included

      string[] keys = Enum.GetNames(typeof(PermissionKind));

 

      //load the base permissions

//more efficient pattern demonstrated

//later in this post

      ctx.Load(rd.BasePermissions);

      ctx.ExecuteQuery();

 

      //get a reference to the base permissions

      //in this RoleDefinition

      BasePermissions bp = rd.BasePermissions;

 

      //enumerate the enum

      foreach (string key in keys)

      {

if (bp.Has((PermissionKind)Enum.Parse(typeof(PermissionKind),

      key)))

{

      //do something

}

      }

}

Okay, so what if we want to see the rights associated with a list or item?  In that case it’s slightly different – instead of working with a collection of RoleDefinitions we work with a collection of RoleAssignments.  Here’s an example of just such a thing for a List:

//get the list

List curList = ctx.Web.Lists.GetByTitle(“My List Title”);

 

//load the RoleAssignments in the list

ctx.Load(curList.RoleAssignments)

 

//execute query

ctx.ExecuteQuery();

 

//enumerate results

foreach(RoleAssignment ra in curList.RoleAssignments)

{

      //do something

}

 

Retrieving the permissions on an item is essentially exactly the same:

 

ListItem curItem =

ctx.Web.Lists.GetByTitle(“My List Title”).GetItemById(3);                       

 

//load the RoleAssignments in the item

ctx.Load(curItem.RoleAssignments)

 

//execute the query and enumerate the RoleAssignments collection

//not shown here, see the list example

 

There are a couple of interesting twists here to consider.  The first is, what if I want to reuse as much of this code as possible and not write all this stuff twice – once for a List and once for a ListItem?  Also, one of the more interesting properties of the RoleAssignment is the Member.  The Member property is an object of type Principal and includes things like the Id, PrincipalType and Title.  As you’ve probably noticed by now, having the Id for items is pretty valuable because many collections have a GetById or GetItemById method to retrieve an individual member of the collection.

 

Let’s talk about the second problem first – getting the values for a property that is an object property (rather than a value property, like a string, int, etc.).  The simplistic way to deal with the problem would be to say okay, let’s load up our collection of RoleAssignments.  As we enumerate each one we’ll retrieve the Member property.  This is definitely doable and would look something like this (borrowing from our example above):

 

//enumerate results

foreach(RoleAssignment ra in curList.RoleAssignments)

{

      Principal p = ra.Member;

      ctx.Load(p);

      ctx.ExecuteQuery();

      //do something with p

}

 

Okay, yeah, it works, but look at the amount of network traffic and server requests we’re generating – one call across the network and one hit on the server for every single RoleAssignment we have in the collection.  Using some of the crazy LINQ syntax that I’m sure we’ll all become increasingly familiar with though, you can retrieve both the RoleAssignment and the Member, as well as the RoleDefinitionBindingsCollection all at once.  Here’s what that LINQ syntax looks like:

 

IEnumerable<RoleAssignment> roles = null;

 

//our query code

roles = ctx.LoadQuery(

curList.RoleAssignments.Include(

      roleAsg => roleAsg.Member, 

      roleAsg => roleAsg.RoleDefinitionBindings.Include(

roleDef => roleDef.Name, // for each role def, include roleDef’s Name

      roleDef => roleDef.Description)));

Now when we enumerate the RoleAssignments collection we have all the details on the RoleAssignment, as well as the values we care about for our object property.  This is pretty slick.  Now to address the first part of the problem posed above – I want to get better code reuse.  While the LINQ statement above is interesting, the last thing I want to do is to write it twice and try to keep it in sync to retrieve the RoleAssignment info for both a List and ListItem.  Well the good news is that both of these classes inherit from SecurableObject.  So, we can modify our code above slightly to use it like this:

 

SecurableObject curObj = null;

 

if (someBooleanThatSaysUseAListIsTrue)

{

      //get the list

curList = ctx.Web.Lists.GetByTitle(“My List Title”);

 

      //do whatever I’m gonna do with the list

 

      //plug it into our query object

      curObj = curList as SecurableObject;

}

else

{

      //get the list item

ListItem curItem =

ctx.Web.Lists.GetByTitle(“My List Title”).GetItemById(3);                       

 

      //do whatever I’m gonna do with the item

 

      //plug it into our query object

      curObj = curItem as SecurableObject;

}

 

//our query code

roles = ctx.LoadQuery(

curObj.RoleAssignments.Include(

      roleAsg => roleAsg.Member, 

      roleAsg => roleAsg.RoleDefinitionBindings.Include(

roleDef => roleDef.Name, // for each role def, include roleDef’s Name

      roleDef => roleDef.Description)));

//execute the query

ctx.ExecuteQuery();

And there we go, we just solved two problems with one fairly nice chunk of code.  Now a few quick hit tasks.  Want to create a user and add them to a SiteGroup:

//get the connection

ClientContext ctx = new ClientContext(“http://foo&#8221;);

 

//get the group

Group grp = ctx.Web.SiteGroups.GetById(MyGroupId);

 

//create the user object

UserCreationInformation usr = new UserCreationInformation();

usr.LoginName = “foo\steve”;

usr.Email = “steve@foo.com”;

usr.Title = “Microsoft Human”;

 

//add it to the group

grp.Users.Add(usr);

 

//execute the query to add the user

ctx.ExecuteQuery();

Okay, how about creating a new Role (i.e. Permission Level):

//get the connection

ClientContext ctx = new ClientContext(“http://foo&#8221;);

 

//create a new base permission

BasePermissions perms = new BasePermissions();

 

//left as an exercise for the reader to decide what

//perms there are and which ones you want to add to

//your custom role.  For each perm you want to add

//you would do something like this (assuming that “p” is a string

//that corresponds to a BasePermission enum name                 

perms.Set((PermissionKind)Enum.Parse(typeof(PermissionKind), p));

 

//create the construct for a new role definition

RoleDefinitionCreationInformation rdInfo = new

      RoleDefinitionCreationInformation();

 

//set the perms

rdInfo.BasePermissions = perms;

 

//set a description

rdInfo.Description =

“A role definition created with the client object model”;

 

//set the name

rdInfo.Name = “Your Custom Role”;

 

//add the definition to the web collection

RoleDefinition rd = ctx.Web.RoleDefinitions.Add(rdInfo);

 

//execute to create

ctx.ExecuteQuery();

Cool.  Moving right along, add a user to a Role:

//get the connection

ClientContext ctx = new ClientContext(“http://foo&#8221;);

 

//get the group

RoleDefinition rd =

      ctx.Web.RoleDefinitions.GetByName(“Your Custom Role “);

 

//get the user object

Principal usr =

ctx.Web.EnsureUser(“foo\steve”);

 

//create the role definition binding collection

RoleDefinitionBindingCollection rdb = new

RoleDefinitionBindingCollection(ctx);

 

//add the role definition to the collection

rdb.Add(rd);

 

//create a RoleAssigment with the user and role definition

ctx.Web.RoleAssignments.Add(usr, rdb);

 

//execute the query to add everything

ctx.ExecuteQuery();

We’re on a “role” now.  Ha ha, couldn’t resist (it’s late Friday night for those of you wondering).  How about creating a group and adding it to a role?

//get the connection

ClientContext ctx = new ClientContext(“http://foo&#8221;);

 

//get the group

RoleDefinition rd =

      ctx.Web.RoleDefinitions.GetByName(“Your Custom Role”);

 

//create the group

GroupCreationInformation grpInfo = new GroupCreationInformation();

grpInfo.Title = “Your New Group”;

grpInfo.Description = “A custom group created with the client object model”;

 

//add it to the list of site groups

Group grp = ctx.Web.SiteGroups.Add(grpInfo);

 

//create the role definition binding collection

RoleDefinitionBindingCollection rdb = new

      RoleDefinitionBindingCollection(ctx);

 

//add the role definition to the collection

rdb.Add(rd);

 

//create a RoleAssigment with the group and role definition

ctx.Web.RoleAssignments.Add(grp, rdb);

 

//execute the query to add everything

ctx.ExecuteQuery();

And last but not least, let’s break inheritance on a list and add a user to a role on that item:

//get the connection

ClientContext ctx = new ClientContext(“http://foo&#8221;);

 

//get the group

RoleDefinition rd = ctx.Web.RoleDefinitions.GetByName(“Your Custom Role”);

 

//get the list

List theList = ctx.Web.Lists.GetByTitle(“My List Title”);

 

//break the inheritance

theList.BreakRoleInheritance(true);

 

//create the role definition binding collection

RoleDefinitionBindingCollection rdb = new

      RoleDefinitionBindingCollection(ctx);

 

//add the role definition to the collection

rdb.Add(rd);

 

//get the user object

Principal usr =

ctx.Web.EnsureUser(“foo\steve”);

 

//*************************************************************

//NOTE:  IF WE WANTED TO REMOVE A USERS’S PERMISSIONS TO A LIST

//OR ITEM OUR CODE WOULD BE LIKE THIS:

//theList.RoleAssignments.GetByPrincipal(usr).DeleteObject()

               

//*************************************************************

 

//create a RoleAssigment with the group and role definition

theList.RoleAssignments.Add(usr, rdb);

 

//execute the query to add everything

ctx.ExecuteQuery();

Whew!  That’s it.  It was a whole lot of code but a ton of fun in the process.  Hopefully you again got a feel for the patterns and common classes involved when managing security through the client object model.  You’ll find it quite powerful for managing your site. 

 

Coming Next…

We’ve covered a lot of ground so far in this series, but we’ve got one last stop – managing web parts using the client object model.  That will be the focus of the next and final posting in this series.

10 thoughts on “Using the SharePoint 2010 Client Object Model – Part 5

  1. Thanks for every other wonderful article. The place else may anyone get that type of
    information in such a perfect means of writing?
    I’ve a presentation subsequent week, and I’m at
    the look for such info.

    Like

  2. Thanks for one’s marvelous posting! I certainly enjoyed reading it, you might
    be a great author.I will remember to bookmark your blog and
    will eventually come back someday. I want to encourage you continue your great
    work, have a nice morning!

    Like

  3. I have been exploring for a bit for any high-quality articles or weblog posts
    on this sort of house . Exploring in Yahoo I ultimately stumbled upon this site.
    Reading this info So i am happy to show that I’ve an incredibly excellent uncanny feeling I discovered
    exactly what I needed. I most certainly will make sure to don?t put out of your mind this website and provides it a glance on a relentless
    basis.

    Like

  4. Hmm it appears like your website ate my first comment (it was super
    long) so I guess I’ll just sum it up what I wrote and say,
    I’m thoroughly enjoying your blog. I as well am an aspiring blog writer but I’m still new to the whole thing.
    Do you have any points for first-time blog writers?

    I’d definitely appreciate it.

    Like

    • Thanks, my only tip would be I started this by writing things down when I was having trouble figuring something out, so I would have something I could go back and look at myself when the problem occurred in the future. Just turned out that other folks were having similar problems and that’s kind of how it got going.

      Like

  5. Hmm it appears like your website ate my first comment (it was extremely long)
    so I guess I’ll just sum it up what I wrote and say, I’m thoroughly
    enjoying your blog. I as well am an aspiring blog writer but I’m still new to
    everything. Do you have any helpful hints for newbie blog writers?
    I’d definitely appreciate it.

    Like

  6. Can you please let me know how to reset the existing list item permissions to “Read” and add “contribute” permissions to new users along with it.

    Like

Leave a comment