Using the SharePoint 2010 Client Object Model – Part 4

In the first three parts of this series we’ve gone through quite a bit of code that shows how to retrieve data from lists.  In this post, we’re going to show how to actually create a list and manage fields.

In the client object model you’ll see a familiar naming pattern of “someobjectCreationInformation” used to create new items.  Creating a new list is no different – we’re going to use something called the ListCreationInformation class.  I’m going to start out creating an instance of the class that will define my new list:

//create a new listcreationinfo object

ListCreationInformation lc = new ListCreationInformation();

lc.Title = ListTitleTxt.Text;

lc.Description = ListDescTxt.Text;

lc.TemplateType = lt.ListTemplateTypeKind;

So what is this property called TemplateType?  The ListTemplate class has a property called ListTemplateTypeKind that can be used for this purpose.  For my sample application I had previously retrieved a list of ListTemplates using code like this:

//get the connection

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

 

//get the list

ListTemplateCollection ltc = ctx.Web.ListTemplates;

 

//select the items

ctx.Load(ltc);

 

//execute the query

ctx.ExecuteQuery();

 

//enumerate the results

foreach (ListTemplate lt in ltc)

{

     //store it somewhere

}

You obviously can’t follow the code literally here because the lt variable would no longer be in scope in the sample above.  However I wrote it up this way to try and illustrate the concepts more clearly.  So getting back to our ListCreationInformation class, we’ve set the Title, Description and TemplateType properties.  All we need to do now is add it to the collection of lists in the web and execute the query to process our code.  Here’s how we do that:

//create the list

List newList = ctx.Web.Lists.Add(lc);

 

//send the request

ctx.ExecuteQuery();

That’s it – our list has been created.  So what if we want to do the opposite – delete our list?  It’s pretty simple really.  We just get our list and use another common method pattern for deleting items with the client object model:  DeleteObject.  Here’s an example of that:

//get the connection

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

 

//get the list

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

theList.DeleteObject();

 

//execute the query

ctx.ExecuteQuery();

Okay, so we can create and delete lists.  The next step is to be able to enumerate, add and delete fields in that list.  Let’s take a look at that.  Enumerating fields follows what should be a familiar pattern at this point.  We get our parent object – the list – and then load the contents of a collection – the fields.  We execute our query and then we can enumerate all of the items in the collection.  Here’s a sample:

//get the connection

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

 

//get the fields

FieldCollection flds = ctx.Web.Lists.GetByTitle(“My List Title”).Fields;

 

//select the items

ctx.Load(flds);

 

//execute the query

ctx.ExecuteQuery();

 

//enumerate the results

foreach (Field fld in flds)

{

//do something with each field

}

Okay, this is hopefully feeling fairly comfortable at this point.  So how do you think we add a new field?  Well…it’s a little different of course.   The easiest way to do that is just to create the Xml definition of a field and add it that way.  The FieldCollection class has an AddFieldAsXml method designed just for this purpose.  So as you might imagine, we have to get a reference to the FieldCollection for a list, and then call the AddFieldAsXml method.  That looks something like this:

//get the connection

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

 

//get the list

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

 

//add the field

Field fld = theList.Fields.AddFieldAsXml(“some xml”, true,

      AddFieldOptions.DefaultValue);

 

So what does that field xml look like?  Fortunately it is pretty much what you already know from SharePoint 2007.  In fact, you can get the complete schema today for creating a field definition in Xml at http://msdn.microsoft.com/en-us/library/ms437580.aspx.  Here’s a simple example of the Xml I used when putting this demo together:

 

<Field Name=’YouLuvClientOM’ DisplayName=’DoYouLuvtheClientOM’ Type=’Number’ Hidden=’False’ Description=’This is a field I created in the client OM’ />

 

Yep, that’s not too bad at all.  Now keep in mind I still haven’t added my field.  There’s one other thing I wanted to show you.  Different types of fields have different options associated with them.  For example, for a Number field you can set the minimum and maximum value, a Currency field has a currency locale, etc.  You can work with these type-specific properties by coercing your Field instance into type-specific field instance.  In the example above I created a field of type Number.  If I want to set the minimum and maximum properties for the field then I need to coerce it into a class of type FieldNumber.  Here’s how we do that:

 

FieldNumber fldNumber = ctx.CastTo<FieldNumber>(fld);

fldNumber.MaximumValue = 100;

fldNumber.MinimumValue = 35;

fldNumber.Update();

 

Now that I’ve got my field all configured, I only have to phone home to the server to complete the exercise:

 

//execute the query to create the field

ctx.ExecuteQuery();

Okay, last step for this posting – let’s delete a field.  Fortunately it’s very easy and follows a similar pattern to deleting a list:

//get the connection

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

 

//get the list

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

 

//get the field

fld = theList.Fields.GetByTitle(“MyFieldInternalName”);

 

//delete the field

fld.DeleteObject();

 

//execute the query

ctx.ExecuteQuery();

And there we go – our field is deleted, again using the familiar pattern of someClass.DeleteObject().  Hopefully by now you are seeing that the client object model is a whole lot more powerful and easy to use than the web services that were included in SharePoint 2007.  No complex Xml to work with, no proxies to deal with, just the warm safe comfortable feeling of tooling around your garden variety object model. 

Coming Next…

We’re not done yet.  In the next post in this series I’ll walk you through working with security in the client object model.

Using the SharePoint 2010 Client Object Model – Part 3

In the first two parts of this posting I described the pattern you can use to retrieve data with the client object model (“client OM”).  I showed how to use the same pattern to retrieve both a set of lists, as well as data contained within a single list.  In this post we’ll talk about ways that we can create and use filters when querying for data via the client OM.

I won’t rehash our pattern all over again.  Suffice to say, it’s exactly the same, and the only part we are playing with here is step 2 – creating the statement to return the data and selecting which fields to return.  Creating the connection and executing the query remain the same:

//create the connection

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

//execute the query

ctx.ExecuteQuery();

For this release, the semantics of creating a query, ordering the results, etc. are going to be controlled by CAML.  So as we saw in the previous posting, we use an instance of the CamlQuery class to do that.  The CAML syntax has not changed between versions, so all the CAML you know and love will still be useful in the client OM. 

From an implementation standpoint, the CamlQuery class has a property called ViewXml, and even though it may not be obvious from the property name, that’s where you plug in your criteria for your query as well.  The ViewXml property expects to have a parent element called <View>, and then within it you add a <Query> and <Where> element to implement your criteria.

Suppose, for example, you want to retrieve all items from your list where the Title property equals Steve.  Your code would look something like this:

CamlQuery cq = new CamlQuery();

cq.ViewXml = “<View><Query><Where><Eq><FieldRef Name=’Title’/><Value Type=’Text’>Steve</Value></Eq></Where></Query></View>”;

As you can see it’s just standard CAML that is going in our ViewXml property.  To use our CAML in our query, we go back to our List and call its GetItems method, returning an instance of a ListItemCollection.  Here’s an example:

ListItemCollection lic = lst.GetItems(cq);

Just as you do with CAML in SharePoint 2007, you can also include sorting in your queries too.  Here’s an example where I’m only sorting on one field, and I’m doing so in descending order (the default sort order is ascending):

cq.ViewXml = “<View><Query><Where><Eq><FieldRef Name=’Title’/><Value Type=’Text’>Steve</Value></Eq></Where><OrderBy><FieldRef Name=’ID’ Ascending=’False’/></OrderyBy></Query></View>”;

 

Now remember in the first two postings in this series where I talked about trying to choose the specific fields you wanted when executing a query, and how that impacts the size of the data sent over the wire?  And I also showed a way in which you could get non-default properties returned when you asked for a ListItemCollection.  Well I’m going to combine those two concepts now as we talk about loading our data.  So far I’ve shown you a couple of ways to instruct the client OM to load up property values in a ListItemCollection (where “lic” is ListItemCollection):

METHOD #1:

ctx.Load(lic);

METHOD #2:

ctx.Load(lic, items => items.IncludeWithDefaultProperties(item => item.DisplayName));

Another way to set the list of properties retrieved is with a hybrid approach between these two models.  We can use a Lambda expression and define every single property that we want returned for the ListItemCollection.  In this example, suppose we only really need to see the ID, Title and DisplayName values.  Here is how we would express that:

METHOD #3:

ctx.Load(lic, itms => itms.Include(

                        itm => itm[“ID”],

                        itm => itm[“Title”],

                        itm => itm.DisplayName));

Not only is it arguably the clearest code in terms of plainly stating what fields we’re going to return, it also delivers the data in the smallest payload by a wide margin.  Here’s the size of the resulting data over the wire for each of the three methods above:

Method #

Payload Size

1

13.4K

2

13.6K

3

2.5K

 

Again, it may not look like a huge difference when you examine the raw numbers, but over time, with lots of clients, or over a slow or latent network it can really add up.  You can also control the number of items that are returned in a query.  You can do it in CAML, or you can do it in your Lambda for setting the fields to be returned.  Here’s an example of each method to limit the number of rows returned to 3.

CAML:

cq.ViewXml = “<View><RowLimit>3</RowLimit></View>”;

Lambda:

ctx.Load(lic, itms => itms.Take(3).Include(

                        itm => itm[“ID”],

                        itm => itm[“Title”],

                        itm => itm.DisplayName));

What else can we do?  The CamlQuery class is also used for paging queries, and lets you set the FolderServerRelativeUrl so you can effectively execute your queries in the subfolder of a list.  Paging queries are a little more unique, so here’s a skeleton of how that would be implemented; note this is just for illustrative purposes, not necessarily a real scenario of how one would want to use paging:

//initialize a paging instance

ListItemCollectionPosition pos = null;

 

while (true)

{

//create the CAML query

CamlQuery cq = new CamlQuery();

 

//set our paging position and view xml

cq.ListItemCollectionPosition = pos;

cq.ViewXml = “<View><ViewFields><FieldRef Name=’ID’/><FieldRef

Name=’Title’/><FieldRef Name=’Body’/></ViewFields>

<RowLimit>2</RowLimit></View>”;

                       

//get items using our CAML class

ListItemCollection lic = lst.GetItems(cq);

 

//load the items up – note how I have to ask separate for ListItemCollectionPosition

//if I don’t, it will say property not initialized when I try and

//work with it below

ctx.Load(lic, itms => itms.ListItemCollectionPosition,

itms => itms.Include(

itm => itm[“ID”],

            itm => itm[“Title”],

      itm => itm.DisplayName));

 

//execute the query

ctx.ExecuteQuery();

 

//get our new paging position

pos = lic.ListItemCollectionPosition;

 

//enumerate each item

foreach (ListItem l in lic)

{

ItemsLst.Items.Add(l[“Title”]);

}

 

//see if we’ve reached the end

if (pos == null)

break;

else

Debug.WriteLine(pos.PagingInfo);

}

Coming Next…

So, what other things can we do?  Surprisingly, a lot.  You can manage security in your site, you can create new lists, you can change the fields in a list, you can even add custom menu items, all with the client OM.  I’ll cover some of these other random things in the future posts in this series.

Using the SharePoint 2010 Client Object Model – Part 2

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

 

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:

 

ctx.Load(lic);

 

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

ctx.ExecuteQuery();

 

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)

{

ItemsLst.Items.Add(l[“Title”]);

}

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.

Coming Next…

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.

Using the SharePoint 2010 Client Object Model – Part 1

SharePoint 2010 introduces a new client side object model (hereafter referred to as the “client OM”) for retrieving data.  It supports a subset of functionality contained in the server side object model, but generally speaking gives you ready access to the data in your SharePoint site using standard object model nomenclature.  Before I actually get into the “codey” part of this posting, let me give a BIG SHOUT OUT to Shaofeng and Michael for giving me tips, tricks, pointers and a cheat sheet that were major sources of information as the code behind this six part blog posting was created.  Thank you fellas!

The object model structure is very similar to what you’ve all known to expect, only with an interceding “Client” in the namespace.  For example, in the server object model you have:

·         Microsoft.SharePoint.SPSite

·         Microsoft.SharePoint.SPWeb

·         Microsoft.SharePoint.SPList

In the client object model you have:

·         Microsoft.SharePoint.Client.Site

·         Microsoft.SharePoint.Client.Web

·         Microsoft.SharePoint.Client.List

You “get connected” to your data in SharePoint with the new ClientContext class.  It is the uber class through which you issue queries and retrieve data from the farm.  Where things get tricky is that when you return objects from a call, they have no data until you execute a query to retrieve them.  The underlying goal here is to create a unified programming experience whether you are coding in SilverLight, ECMA (can I please just call it javascript the rest of the way??) and .NET managed applications.  The client OM forces some of these semantics upon you, but in return it a) provides you data, b) minimizes the amount of data sent over the wire, and c) minimizes the number of roundtrips to the server.  So how do these things work together?

Let’s start with a relatively simple example – getting a list of all the lists in your SharePoint site.  First, I added a reference to Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll.  I then added this using statement at the top of my class:

using Microsoft.SharePoint.Client;

Now, to begin with we need to create our instance of the ClientContext class, which is going to form our connection:

PATTERN STEP 1:  CREATE A CLIENT CONNECTION

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

 

 

Now we’ll start to use some of the built in properties of the ClientConnection class, starting with the Web for the current site (remember, it’s a “Web” and not “SPWeb” because we are using the client OM):

 

Web w = ctx.Web;

 

Now we have our object (w), but we still have no data.  We’re going to tell the client OM that we want to populate the collection of lists.  We use LINQ to do this, but there are a few different ways in which this can be accomplished; here is the simplest way.

 

PATTERN STEP 2: CREATE THE STATEMENT TO RETRIEVE THE DATA

var lists = ctx.LoadQuery(w.Lists);

 

Note that in the example above it will return a default set of properties.  We could also pass in the list of properties that should be retrieved (we’ll look at that method in a bit). We still haven’t made a round trip to the server, we’ve just defined what data we want returned.  To actually populate the collection of lists, we have to call the ExecuteQuery method on our ClientContext instance.  Note that when you do call it though, LoadQuery affects ONLY the local variable named “lists”.  It does not affect the ClientContext (specifically, w.Lists).  In other words, after ExecuteQuery() is called the following will work:

 

foreach (List L in lists) {..}

 

the following will NOT work:

foreach (List L in w.Lists) {..}

 

Now, executing the query and getting our data back is our next line of code:

 

PATTERN STEP 3: EXECUTE THE QUERY

ctx.ExecuteQuery();

 

When we call ExecuteQuery, we actually send our request from the client to the server.  The response is going to include all of the data we need, based on our LINQ query and the fields that we’ve asked for.  The data comes back to us as simple formatted text that works well with JSON and REST.  Here is snippet of the data that’s returned for each list when we asked for the default properties as shown above:

 

{

“_ObjectType_”:”SP.List”,”_ObjectIdentity_”:”740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:a496a84e-e865-4267-8bdc-b1b46df990de:list:ebcb8888-2892-440e-a80d-53c1c78b7339″,”_ObjectVersion_”:”3″,”ParentWebUrl”:”\u002f”,”HasExternalDataSource”:false,

“Created”:”\/Date(1256585338000)\/”,”LastItemModifiedDate”:”\/Date(1256585451000)\/”,”LastItemDeletedDate”:”\/Date(1256585338000)\/”,”Id”:”\/Guid(ebcb8888-2892-440e-a80d-53c1c78b7339)\/”,”Description”:”A test list”,”Title”:”BigList”,”Direction”:”none”,”BaseType”:0,

“ImageUrl”:”\u002f_layouts\u002fimages\u002fitdatash.png”,”ItemCount”:3000,”BaseTemplate”:120,

“DefaultContentApprovalWorkflowId”:”\/Guid(00000000-0000-0000-0000-000000000000)\/”,”TemplateFeatureId”:”\/Guid(00bfea71-3a1d-41d3-a0ee-651d11570120)\/”,”DefaultViewUrl”:”\u002fLists\u002fBigList\u002fBig View.aspx”,”DefaultEditFormUrl”:”\u002fLists\u002fBigList\u002fEditForm.aspx”,

“DefaultNewFormUrl”:”\u002fLists\u002fBigList\u002fNewForm.aspx”,

“DefaultDisplayFormUrl”:”\u002fLists\u002fBigList\u002fDispForm.aspx”,”EnableAttachments”:true,

“ServerTemplateCanCreateFolders”:true,”EnableFolderCreation”:false,”EnableModeration”:false,

“EnableVersioning”:false,”ForceCheckout”:false,”EnableMinorVersions”:false,

“DraftVersionVisibility”:0,”Hidden”:false,”IsApplicationList”:false,”IsCatalog”:false,

“AllowContentTypes”:true,”DocumentTemplateUrl”:null,”ContentTypesEnabled”:false,

“MultipleDataList”:false,”NoCrawl”:false

}

 

As I noted above, we can also create a query and just ask for specific fields.  To do so we use the Load method on the ClientContext class and a somewhat more complicated LINQ query with Lambdas.  Here is how that works:

 

ctx.Load(w.Lists, lists => lists.Include(prop => prop.Title,

                    prop => prop.Id, prop => prop.Hidden));

 

Basically what we’re saying here is that we want to retrieve items in the Lists property of the Web, we’re going to use a parameter called “lists”, and we’re going to define it as including the Title and Id fields. 

 

We still call the ExecuteQuery after creating our LINQ statement, but here’s what the return data looks like for a single list with a specific list of fields:

{

“_ObjectType_”:”SP.List”,”_ObjectIdentity_”:”740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:a496a84e-e865-4267-8bdc-b1b46df990de:list:ebcb8888-2892-440e-a80d-53c1c78b7339″,”_ObjectVersion_”:”3″,”Title”:”BigList”,”Id”:”\/Guid(ebcb8888-2892-440e-a80d-53c1c78b7339)\/”,”Hidden”:false,”BaseType”:0

}

 

The difference in size is impressive.  In fact for this case I did a trace of both methods – asking for the collection of lists and all default fields resulted in a payload of 59k; calling the method with a list of just the three fields I needed resulted in a payload of 12k.  This all adds up, especially when retrieving data over slow or congested connections.

 

PATTERN BEST PRACTICE: WHENEVER POSSIBLE, PROVIDE A SPECIFIC LIST OF FIELDS WHEN RETRIEVING DATA

 

So now that we’ve made that single round trip to the server, we won’t have to go back to it again in order to finish our example.  With our data in hand, let’s complete the pattern to process the data in our results.  In this case we’re going to enumerate all of the lists that were returned and add it to a list box in a Windows Forms application (NOTE: the example here is based on the code snippet above for retrieving specific fields; if you used the first example of retrieving all, you would enumerate through the var lists return value):

 

foreach (List theList in w.Lists)

{

if(theList.Hidden != true)

ListsLst.Items.Add(theList.Title);

}

One thing that’s important to remember is that when you retrieve items, if they have properties that are object collections, those values will not be retrieved when you query for the item.  As an example, take the ListTemplates property of the Web class.  It is a property of type ListTemplateCollection, filled with individual ListTemplate items.  You won’t get the ListTemplateCollection property populated with the list of ListTemplates if you retrieve the Web object like this:

Web w = ctx.Web;

ctx.Load(w);

ctx.ExecuteQuery();

It will give you all of the simple property values of the Web object but that’s it.  In order to populate those object collection properties, you have to pass them to the Load method like this:

ListTemplateCollection ltc = ctx.Web.ListTemplates;

ctx.Load(ltc);

ctx.ExecuteQuery();

 

//now enumerate foreach(ListTemplate lt in ltc){}

Coming Next…

That’s our basic pattern, and brings this posting to a close.  In part 2 of this posting, I’ll describe how to use this pattern to retrieve data from a list.