How To Quickly and Easily Get a List of Fields in a SharePoint 2013 List

This is going to be the first of two short postings, because while they are related, they are also individually interesting.  I was looking for some CSOM to work with Ratings in SharePoint 2013 and not finding much in the way of documentation.  After deducing that I would have to go a little well-defined CSOM code, and a little “late bound” code, my next problem was to figure out what fields I needed to retrieve.  The fields that hold this content are hidden which makes them tough to figure out using the out of the box UI.  However you can get this information pretty easily using the REST endpoint.  The way to do it is to just enter this in the browser:

https://theSiteName/_api/web/lists/GetByTitle(‘theListName’)/Fields

This gives you a complete XML dump of the list schema.  If you’re using IE though you will probably not see the Xml, but instead get the ever so useful RSS feed viewer.  To get a handle on this quickly I recommend the following:

 

  1. Right-click and select View Source.
  2. Copy everything.
  3. Open up Visual Studio 2012 and add a new Xml document.
  4. Delete the default goo in the document then paste in the Xml from the browser.  It will still look like an unformatted jumble of gooey mess.
  5. On the toolbar you should see an item that looks like a document; if you hover over it the tooltip will say something like “Format the whole document (CTRL + K, CTRL + D).  Click that – XML happiness ensues.

Once you’ve formatted the Xml document you can find your field names in the InternalName element.  Hope that helps.

Advertisements

Using Query Rules with CSOM Queries in SharePoint 2013

I’ve had this question from a few people and never had a chance to track down the answer until today.  I’ve written a few times already about query rules and how awesome they are:  http://social.technet.microsoft.com/Search/en-US?query=%22query%20rules%22&beta=0&rn=Share-n-dipity&rq=site:blogs.technet.com/b/speschka/&ac=8 actually shows 9 postings where I’ve mentioned them in some way or another.  They are pretty freakin’ brilliant, but the question I’ve been getting asked about is whether or not they fire when someone issues a query via CSOM?  Well as it turns out for the most part the answer is yes.  The “for the most part” really means if you are keeping track of where your query rules AND your client context endpoints are, they do. 

For example, suppose you create a query rule in the site collection https://www.foo.com; as long as you create your ClientContext for CSOM operations using the same URL then any query rules in that site collection will be invoked when you execute your query via CSOM.  So in this scenario you would create your ClientContext something like this (there are a few variations to how you can do it, I’m just trying to demonstrate the Url usage): 

ClientContext ctx = TokenHelper.GetS2SClientContextWithWindowsIdentity(new Uri(“https://www.foo.com“), Request.LogonUserIdentity);

(Note that this code snippet is based on a SharePoint App I wrote, which is why it’s using TokenHelper)

The other thing to remember is that you can have your query rules fire for ANY CSOM call if you create them in the Search Service Application.  All query rules there are automatically invoked when a CSOM query comes in, no matter what site collection the ClientContext is connected to.

Using Taxonomy AKA Managed Metadata AKA TermSets with CSOM in SharePoint 2013

I had the occasion to need to figure out accessing the Managed Metadata Store using the new client object model libraries for SharePoint 2013.  In snooping around, I found virtually no documentation on this topic whatsoever, other than generic boilerplate class definitions that have been clearly emitted by some automated process rather than a human who’s actually done any development with it.  So, for those of you looking around the Microsoft.SharePoint.Client.Taxonomy namespace, hopefully this will provide a little kick start to get you headed in the right direction.

The first thing to understand is that, much like the managed code object model, the TaxonomySession is the one that rules them all.  Unfortunately if you look at the fairly arcane MSDN docs on this topic it suggests that there is some usable constructor for this class.  Please look at the dancing monkey in my left hand and ignore that documentation – it is poo.  Instead the way to get started with the TaxonomySession is to create your ClientContext instance first, and then use that to create a new TaxonomySession.  For purposes of this discussion I will skip showing how to create your ClientContext instance because there are a ton of examples out there about how to do that; in my case I’ve written a simple SharePoint App and am using the new model to do the lifting for me there to get my ClientContext.  Once I have that I can get my TaxonomySession like so (“CheckClientContext() is the method I use to get my ClientContext variable, ctx, initialized):

 

CheckClientContext();

TaxonomySession ts = TaxonomySession.GetTaxonomySession(ctx);

 

So at this point I haven’t really done anything…there’s no actual data in my TaxonomySession that I can use, but it’s at least set up for use.  At this point I can now start loading up the collections of data that make up most of the elements in the Managed Metadata Service.  The key thing, like all collections you access via CSOM, is that you need to Load() them with the ClientContext before you try and access any of their members, otherwise you will error out.  So here’s an example of starting to drill down to get the collection of Term Stores (of which there is usually just one, but you get the point – illustrates how to use the collections):

ctx.Load(ts.TermStores);

TermStoreCollection tsc = ts.TermStores;

ctx.ExecuteQuery();

foreach (TermStore tStore in tsc)

{

     //do something here

}

 

From here you should be off and running at least as far as the pattern is concerned for using this.  What I’ll do here is paste some code that I use to enumerate through all the goo in my Managed Metadata Service, down to all of the individual terms.  Not a production app of course, but hopefully a good illustration of how to work your way through the model.  I mean “illustration” figuratively, since the formatting on this site continues to suck eggs:

 

CheckClientContext();

TaxonomySession ts = TaxonomySession.GetTaxonomySession(ctx);

ctx.Load(ts.TermStores);

TermStoreCollection tsc = ts.TermStores;

 

System.Text.StringBuilder sb = new System.Text.StringBuilder(4096);

 

//before referring to any member, need to execute query, i.e.

//TermStore tStore = tsc[0]; or foreach…

ctx.ExecuteQuery();

foreach (TermStore tStore in tsc)

{

    sb.Append(“Term Store: “ + tStore.Name + Environment.NewLine);

    ctx.Load(tStore.Groups);

    ctx.ExecuteQuery();

                   

     foreach (TermGroup tg in tStore.Groups)

    {

        sb.Append(“\t->” + “Term Group: “ + tg.Name + Environment.NewLine);

        ctx.Load(tg.TermSets);

        ctx.ExecuteQuery();

      foreach (TermSet tSet in tg.TermSets)

            {

                sb.Append(“\t\t->” + “Term Set: “ + tSet.Name + Environment.NewLine);

                ctx.Load(tSet.Terms);

                ctx.ExecuteQuery();

                     foreach (Term t in tSet.Terms)

                {

                    sb.Append(“\t\t\t->” + “Term: “ + t.Name + Environment.NewLine);

                }

            }

        }

    }

Debug.WriteLine(sb.ToString());

 

Here you can see an example of the output from my farm:

This should be enough to get you anywhere you need to in the Taxonomy client model.  Enjoy!

 

Using the Client Object Model with a Forms Based Auth Site in SharePoint 2010

One of the questions I’ve seen a few times since my “mega-posting” on the client object model, is how to use it with a SharePoint site that is secured with forms based authentication.  There are actually a couple of ways you could do this.  The more complicated approach that I won’t describe in great detail here is to use the Authentication web service, similar to how I described for SharePoint 2007 in my Forms Based Authentication whitepaper part 2.  Fortunately though, the folks designing the client OM baked in a much simpler way to do this.  The ClientContext class includes an AuthenticationMode and FormsAuthenticationLoginInfo properties to help you manage this.

Here’s an example of using them to get a list of all the lists in the site.  Note this doesn’t follow the advice that I gave in one of the other client OM posts about specifying the properties you want returned, but I just wanted a quick and simple example to demonstrate:

ClientContext ctx = new ClientContext(someSiteUrl);
ctx.AuthenticationMode = ClientAuthenticationMode.FormsAuthentication;
ctx.FormsAuthenticationLoginInfo = new
                    FormsAuthenticationLoginInfo(myUserName, myUserPwd);

//get the web
Web w = ctx.Web;

//LOAD LISTS WITH ALL PROPERTIES
var lists = ctx.LoadQuery(w.Lists);

//execute the query
ctx.ExecuteQuery();

foreach (List theList in lists)
{
        //do something here

}

P.S. As a side note, are you all noticing how much the formatting in these posts STINKS since they upgraded the site?  How unpleasant…

Getting Search Service Applications and Proxies in SharePoint 2010 Object Model

I’ve been doing a lot of digging around this topic this morning for my Search Explorer for Developers application (more on that in a future post).  In general it can be kind of tough to get search service applications and proxies when working without an HttpContext (like in a winforms app).  Even with context, it’s not really a picnic connecting a proxy to a service application.  There may be better ways of doing this, and if/when I find them I’ll happily update this post.  But for now, there are a few key concepts I wanted to cover in here for the OM developer that is trying to get at these service apps and proxies.

First, here’s the code I am using to get all of the search service application proxies in the farm:

var apps = from SPServiceProxy ssp in theFarm.ServiceProxies

           from SPServiceApplicationProxy ssa in ssp.ApplicationProxies

           where ssa.GetType() == typeof(SearchServiceApplicationProxy)

           select ssa;

 

//enumerate results

foreach (SearchServiceApplicationProxy app in apps)

{

      //do something with the proxy here

}

There are a couple of things worth noting here.  First is the use of the double “from” statement in the LINQ query.  I’ve actually found this a pretty good way to dig into some of the collection members in LINQ.  Yes, I know there are other arguably “more elegant” ways to do this.  However, I am a simple human and as such I find this approach is easier to read, understand and develop than some of the more advanced LINQ techniques.  The other thing worth noting here is that this code does NOT retrieve a proxy for the FAST content service applications.  That’s because this special flavor of search service application does not have a proxy.  You will normally have two service applications for each implementation of FAST, but only one proxy.

Next, here’s some code to enumerate all of the search service applications in your farm.  It DOES include all of them, including both FAST content and FAST query:

SearchService s = new SearchService(“OSearch14”, SPFarm.Local);

foreach (SearchServiceApplication ssa in s.SearchApplications)

{

      //do something with the proxy here

}

One thing worth pointing out here is the method and string I used for creating the SearchService instance.  All I’ll say is that this is a method I stumbled upon in Reflector, and I can’t guarantee it will work / be supported at RTM time.  But it is working for now, and to date I haven’t found another non-deprecated method to achieve this same OM goodness.

Next on the list is getting the search service application associated with a specific search service proxy.  I won’t go into the backstory on this, but for now I will just say that this is the approach I’m least pleased with for now.  One day when I’m writing, er rambling, my memoirs I’ll explain why.  In the meantime this is a combination of some of the different methodologies described above:

//use a LINQ query to get the service app because using the Name doesn’t

// work in the searchapplications collection

var srchApp = from SearchServiceApplication sapp in s.SearchApplications

              where sapp.Name == p.GetSearchApplicationName()

              select sapp;

 

SearchServiceApplication serviceApp = srchApp.First();

 

Nothing really to add there, I think that chunk of code is fairly straightforward.  Finally, if you do have an HttpContext it’s a lot easier to get the search service application proxy.  Here are a couple of examples of how you might do that:

//SPServiceContext spc = SPServiceContext.Current;

//OR

//SPServiceContext spc = SPServiceContext.GetContext(SPContext.Current.Site);

//OR

//SPServiceContext spc = SPServiceContext.GetContext(this.Page.Context);

//THEN

//SearchServiceApplicationProxy p =

//(SearchServiceApplicationProxy)SearchServiceApplicationProxy.GetProxy(spc);

So there you go, lots of different ways of working with some common elements of search administration.

Using the SharePoint 2010 Client Object Model – Part 6

Time to wrap up this series and we’re going to mostly talk about managing web parts using the client object model.  First, however, we’re going to take a quick peek at something else you can do, which is create additional Edit Control Block (ECB) menu items.  Yes, you can even create ECB items from the client OM.  Here’s how we do that:

//get the connection

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

 

//get the list

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

 

//load the custom actions collection

ctx.Load(theList.UserCustomActions);

ctx.ExecuteQuery();

               

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

//here’s one way of finding a menu item and deleting it

foreach (UserCustomAction uca in theList.UserCustomActions)

{

if (uca.Title == “My New Menu”)

      {

            uca.DeleteObject();

            break;

      }

}

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

 

//create the custom action

UserCustomAction act = theList.UserCustomActions.Add();

 

//set the properties and update

act.Location = “EditControlBlock”;

act.Sequence = 100;

act.Title = “My New Menu”;

act.Url = “/_layouts/settings.aspx”;

act.ImageUrl = “/_layouts/images/availableworkflow.gif”;

act.Update();

 

//execute the query to add everything

ctx.ExecuteQuery();

There you have it.  Navigate to the site, click to get the ECB menu and you should see your new menu item with the icon you specified for the ImageUrl.  Note that you can also use this same methodology to place an item on the Site Actions menu.  The differences are:

1)      Instead of getting the UserCustomActions collection from a list, get it from the Web

2)      Instead of the location being “EditControlBlock”, it should be “Microsoft.SharePoint.StandardMenu”

3)      You need to set the Group property to “SiteActions”

Try it out and you’ll see it works pretty well.  Now, when we start working with web parts we have one class that probably looks pretty familiar and one new methodology that we haven’t seen yet.  The familiar class is the LimitedWebPartManager, which is the same class that was used in SharePoint 2007 to manage the web parts on a page.  The new methodology is the way in which we get access to the LimitedWebPartManager class – we’re going to do that through the File class in the client object model.  The pattern will start out in the same familiar way – we’ll get our ClientContext.  Next though we’ll instantiate our File class object using the relative path to a web part page.  In a publishing site that will typically be something like “/pages/default.aspx”.  For one of the new team sites it will be something like “/SitePages/Home.aspx”.

Once we have a reference to the web part page, then we can get an instance of the LimitedWebPartManager class and start working with web parts on the page in much the same way we did in SharePoint 2007.   Here’s how that code might look when working with a team site home page:

//get the connection

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

 

//get the home page

File home = ctx.Web.GetFileByServerRelativeUrl(“/SitePages/home.aspx”);

 

//get the web part manager

LimitedWebPartManager wpm =

      home.GetLimitedWebPartManager(PersonalizationScope.Shared);

 

IEnumerable<WebPartDefinition> wpds = null;

 

//create the LINQ query to get the web parts from

//the web part definition collection

wpds = ctx.LoadQuery(

wpm.WebParts.Include(

      wp => wp.Id,

      wp => wp.WebPart));

 

//load the list of web parts

ctx.ExecuteQuery();

 

//enumerate the results

if (wpds.Count() == 0)

//no web parts found on this page

else

{

foreach (WebPartDefinition wpd in wpds)

{

//do something with the web part definition,

                  //or the web part via its WebPart property

            }

}

That’s how we can enumerate through all of the web parts on any web part page.  Now let’s suppose that we want to change a property on the web part.  We use a similar pattern to what has been demonstrated in the earlier posts in this series.  We can get it by Id and then work with it.  Here’s an example of doing that to change the Title property of the part.  Note that the code below includes a checkout and checkin.  It obviously isn’t usually necessary for a team site but is for a publishing site.  If you’re not sure, you can call checkin and checkout and it won’t hurt if the list doesn’t require it.

//get the connection

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

 

//get the home page

File home = ctx.Web.GetFileByServerRelativeUrl(“/SitePages/home.aspx”);

 

//get the web part manager

LimitedWebPartManager wpm =

      home.GetLimitedWebPartManager(PersonalizationScope.Shared);

 

//load the web part definitions

ctx.Load(wpm.WebParts);

ctx.ExecuteQuery();

 

//checkout in case it’s needed; doesn’t hurt if it doesn’t

home.CheckOut();

 

//get the web part definition

WebPartDefinition wpd =

      wpm.WebParts.GetById(MyWebPartId);

 

//set the title

wpd.WebPart.Title = “My Web Part Title”;

 

//save changes

wpd.SaveWebPartChanges();

 

//checkin in case it’s needed; doesn’t hurt if it doesn’t

home.CheckIn(string.Empty, CheckinType.MajorCheckIn);

 

//execute the query to save changes

ctx.ExecuteQuery();

Okay, now for my final trick we’ll look at how to add and delete web parts from a page.  To add a web part I’m going to wimp out a little and just show an example of adding a web part by using a chunk of Xml.  You can obviously do it other ways, such as providing the assembly and class as well.  You would do that by creating a new instance of the WebPart class and then using the LimitedWebPartManager to add it to the page.  This is essentially the same process I covered for SharePoint 2007 in my blog posting about customizing My Sites, which you can find at http://blogs.msdn.com/sharepoint/archive/2007/03/22/customizing-moss-2007-my-sites-within-the-enterprise.aspx.  As a side note this process will be much easier in SharePoint 2010 by using the new site created event.  But I digress; here’s the code to add a web part to a page using a chunk of Xml:

//get the connection

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

 

//get the home page

File home = ctx.Web.GetFileByServerRelativeUrl(“/SitePages/home.aspx”);

 

//checkout in case it’s needed; doesn’t hurt if it doesn’t

home.CheckOut();

 

//get the web part manager

LimitedWebPartManager wpm =

      home.GetLimitedWebPartManager(PersonalizationScope.Shared);

 

string webPartXml =

                “<?xml version=\”1.0\” encoding=\”utf-8\”?><WebPart xmlns:xsi=\”http://www.w3.org/2001/XMLSchema-instance\” xmlns:xsd=\”http://www.w3.org/2001/XMLSchema\” xmlns=\”http://schemas.microsoft.com/WebPart/v2\”>  <Title>My test web part</Title>  <FrameType>Default</FrameType>  <Description>Use for formatted text, tables, and images.</Description>  <IsIncluded>true</IsIncluded>  <ZoneID>Header</ZoneID>  <PartOrder>0</PartOrder>  <FrameState>Normal</FrameState>  <Height />  <Width />  <AllowRemove>true</AllowRemove>  <AllowZoneChange>true</AllowZoneChange>  <AllowMinimize>true</AllowMinimize>  <AllowConnect>true</AllowConnect>  <AllowEdit>true</AllowEdit>  <AllowHide>true</AllowHide>  <IsVisible>true</IsVisible>  <DetailLink />  <HelpLink />  <HelpMode>Modeless</HelpMode>  <Dir>Default</Dir>  <PartImageSmall />  <MissingAssembly>Cannot import this Web Part.</MissingAssembly>  <PartImageLarge>/_layouts/images/mscontl.gif</PartImageLarge>  <IsIncludedFilter />  <Assembly>Microsoft.SharePoint, Version=13.0.0.0, Culture=neutral, PublicKeyToken=94de0004b6e3fcc5</Assembly>  <TypeName>Microsoft.SharePoint.WebPartPages.ContentEditorWebPart</TypeName>  <ContentLink xmlns=\”http://schemas.microsoft.com/WebPart/v2/ContentEditor\” />  <Content xmlns=\”http://schemas.microsoft.com/WebPart/v2/ContentEditor\”><![CDATA[This is my test text! <DIV>&nbsp;</DIV><DIV>Blah blah blah</DIV><DIV>&nbsp;</DIV><DIV>And another blah</DIV>]]></Content>  <PartStorage xmlns=\”http://schemas.microsoft.com/WebPart/v2/ContentEditor\” /></WebPart>”;

 

//create the web part definition

WebPartDefinition newWpd = wpm.ImportWebPart(webPartXml);

 

//add the web part

wpm.AddWebPart(newWpd.WebPart, “Left”, 1);

               

//checkin in case it’s needed; doesn’t hurt if it doesn’t

home.CheckIn(string.Empty, CheckinType.MajorCheckIn);

 

//execute the query to add everything

ctx.ExecuteQuery();

And now, we delete a web part from the page:

//get the connection

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

 

//get the home page

File home = ctx.Web.GetFileByServerRelativeUrl(“/SitePages/home.aspx”);

 

//checkout in case it’s needed; doesn’t hurt if it doesn’t

home.CheckOut();

 

//get the web part manager

LimitedWebPartManager wpm =

      home.GetLimitedWebPartManager(PersonalizationScope.Shared);

 

//load the web part definitions

ctx.Load(wpm.WebParts);

ctx.ExecuteQuery();

 

//get the web part

WebPartDefinition wpd = wpm.WebParts.GetById(MyWebPartId);

 

//delete the part

wpd.DeleteWebPart();

 

//checkin in case it’s needed; doesn’t hurt if it doesn’t

home.CheckIn(string.Empty, CheckinType.MajorCheckIn);

 

//execute the query to do the deletion

ctx.ExecuteQuery();

There you go folks, a pretty good run through the different features of the client object model.  Hopefully you can appreciate now all of functionality this new set of classes provides, and it instills happy happy joy joy feelings in SharePoint developers everywhere.  I hope you found this series useful and can start writing some killer client object model applications out there.  I had a lot of fun putting this together and hope you enjoyed it too.

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&#8221;);

               

//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.