In part 1 of this post, I described some general features of the new client object model (“client OM”) that is included with SharePoint 2010. I also walked through a pattern for retrieving a collection of all of the lists in a web using that object model. In this posting, we’ll extend our example further and we’ll retrieve data from an individual list. Some if it will be redundant from the first posting, but in a way that’s what you would hope for if we’re using a pattern, right? Also, like part 1, this posting will be in C#. I promise the next topic in which I post code I will use VB.NET.
PATTERN STEP 1: CREATE A CLIENT CONNECTION
ClientContext ctx = new ClientContext("http://foo");
Like part 1, we’re going to use properties of the ClientContext class in order to get to the web and list we want to work with. Unlike part 1, we’re going to pass in a parameter to our List object to define the name of the list we want to retrieve.
List lst = ctx.Web.Lists.GetByTitle("My List Name");
Now that we have our list information defined, we need to define the items that we’re going to retrieve. To get the lists in the first posting we used a LINQ query again to define the shape of our data. Lists items are going to be different. From this point forward we are back to working with our old friend CAML.
PATTERN STEP 2: CREATE THE STATEMENT TO RETRIEVE THE DATA
The client OM provides a couple of different ways to work with CAML to retrieve data. It has a CamlQuery class that we are always going to use to retrieve the items. In this particular case we are going to assume that we have a list with relatively few items, and we want to retrieve every single item in the list. So here’s how we can create a new instance of the CamlQuery class for that purpose:
CamlQuery cq = CamlQuery.CreateAllItemsQuery();
Now we’ve created our CamlQuery, we have to actually use it to retrieve data. The means by which we do that is very similar to the SharePoint 2007 and the way we use CAML in the server side object model – we pass our CamlQuery instance into a method on the List to retrieve the data. The return value from the GetItems method on the client OM’s List class is a ListItemCollection. So here’s how we tie it all together:
ListItemCollection lic = lst.GetItems(cq);
Just as we demonstrated in the first posting, we now need to call one of the methods on the ClientContext class so it will know that it needs to load our data when it executes the query. Again, using the simple case, we can just call the Load method:
As I described in part 1, we want to select the specific fields we want to retrieve in order to minimize the amount of data we send over the wire, and the simple query syntax doesn’t let you do so. We’ll discuss that concept in part 3 of this series.
PATTERN STEP 3: EXECUTE THE QUERY
As demonstrated in part 1, here we execute the query and return results. This also validates our pattern – we retrieved an entirely different set of data, but we were able to use the same pattern to do so. Now that we have our data, we can enumerate the results and add it to our list box:
foreach (ListItem l in lic)
So, there we have it – all the data in your lists returned. There is something important to remember too when you are using a simple Load statement with a ListItemCollection parameter (i.e. ctx.Load(lic)). Four properties of ListItem are not available by default when you return list items: DisplayName, EffectiveBasePermissions, HasUniqueRoleAssignments, and RoleAssignments. If you tried to reference them in your code, you will get a Property not initialized error. For example, this line of code would result in an error: ItemsLst.Items.Add(l.DisplayName);.
In order to retrieve them, you have to specifically ask to have them included when you define your query. There are multiple ways to do this, so I will just cover one fairly straightforward way here. When you define your query you can add a Lambda expression that tells the client OM some additional properties you want in addition to the default properties. It uses the IncludeWithDefaultProperties method, and looks like this:
ctx.Load(lic, items => items.IncludeWithDefaultProperties(item => item.DisplayName));
So in this example we’re retrieving all of the default properties, as well as the DisplayName property of each list item. This same method can be used to retrieve other non-default properties. For example, suppose you have a list with a column called Supervisor, you could retrieve it, DisplayName and the default properties like this:
ctx.Load(lic, items => items.IncludeWithDefaultProperties(
item => item.DisplayName,
item => item["Supervisor"]));
That’s just a hint of the different ways in which you can customize the data returned in a query. We’ll be covering more of these options in our next post.
That’s it for this posting. Hopefully the client OM is making more sense to you now and you have a pretty good feel for the pattern we can use to retrieve data. In part 3 of this post I’ll talk about creating filters when retrieving your data.