- Part 1: Introduction and Basics
- Part 2: Deploy & Download
- Part 3: The Client Side Object Model (this post)
- Part 4: Functions, Objects and Classes
- Part 5: Avoid the Global Namespace *
- Part 5: Download & Caching *
- Part 6: Efficiency & Performance*
- Part 7: Testing *
- Part 9: Error Handling *
- Part 10: Advanced Topics *
- Part 11: Security *
- Part 12: Implementing Business Logic *
- Part 13: Tools and Resources *
- Part 14: Wrap-Up *
*: Coming Soon…
Synopsis and Key Take-Aways
- The code runs off of the SharePoint server in the users browser
- The code can still interact with SharePoint at a pretty low level – retrieving content from SharePoint, creating and modifying content stored in SharePoint, modifying aspects of SharePoint itself (managing lists and libraries, pages web parts, etc.)
To give you an idea of what is possible before going into detail, here are a few things that can be done from the CSOM:
- Full CRUD (Create, Read, Update & Delete) capabilities for List Items, Lists, Content Types, Webs and other key objects.
- Add web parts to a page
- Remove web parts form a page
- Create new workflows associations for existing workflow templates
- Work with user permissions for securable objects
- Manage security groups
- Activate/deactivate Features from a given scope
- Manage fields on lists, libraries and content types
- Work with files in document libraries
- …and a whole lot more…
Not everything is available in the CSOM – some areas of SharePoint simply cannot be accessed by code utilizing the CSOM. More on this in a moment. In addition, some requirements are best met with server side code – see below for details.
What Can We Access?
In general, CSOM code can interact with SharePoint at the site collection level and below. This means that the following are available:
- SPSite (although we can’t reach outside of our current site collection)
- web parts
When analyzing requirements to determine whether CSOM is an option, consider the level of access required. In general, if it is within a single collection, you can probably do it with CSOM.
What Scenarios Don’t Work?
- Processing large amounts of data – pulling all of that data across the wire down to the client may not be a good way to process it
- Security concerns – pulling data across the wire to process it without some type of encryption (e.g. SSL) may present security problems
- Code that needs to run whether users are connected to and browsing your site or not, for example workflows and timer jobs.
- Code that must respond to server-side events, such as after an item has been added to the database
At the most basic level, you must commit a batch of commands prior to interacting with the properties of any objects referenced in the commands. An example will help to clarify this:
Don’t worry about the details of what’s going on in that code sample for now. We’ll look into those details later. Read the comments to get an understanding of the code, but here are the things you need to know to understand the batch process:
- All of the code from line 1 to line 18 runs on the client and has no interaction with the server. For example, on line 4, the call to getItemById does not actually connect to the server and grab a reference to the SPListItem. It simply adds the command(s) to the list of commands queued up to be committed (this is the “batch” referred to earlier)
- Line 19 commits the batch to the server. When this line executes, the batch is packaged up and sent across the wire to the server. The server executes the code we’ve told it to run and returns a result to our page.
- Line 19 also registers 2 callback methods – one for if the batch runs successfully (on lines 22-24), one if the batch fails (on lines 26-28). After the batch has returned form the server, the appropriate callback method is run and the items collected in lines 1-18 (list & listItem) are available for use.
- Line 23 references one of the properties from the listitem (specifically the Title property) that is now available to us because we have committed the batch to the server and gotten a populated ListItem back.
Things to Know About Batching and Objects
The batch operations have a couple of quirks that are important to know.
Scalar and Collection Properties
Besides the fact that CSOM operates in batches like this, the only really important thing to know about the batched nature of CSOM operations is how we go about accessing objects and their properties in a CSOM application.
For example, consider the following code:
This code is responsible for filling up the (in this case) web object so that we can access its properties. It is important to note, however, that not all properties of the object are filled up (populated) by this command. It is only the scalar (i.e. non-collection) properties that will have data after a load command and its corresponding executeQueryAsyc command. In other words, simple properties – ones with data types like string, int, bool, etc. are populated. Properties that contain collections are not populated; they must be explicitly filled up. In the case of the Web object, the following are examples of properties that would be populated after a call to load like we have in the code above:
These are all simple scalar properties. (Note that this is not an exhaustive list of the scalar properties, and each object has its own collection of scalar properties.)
On the other hand, collection properties such as the following are not populated by the call to load shown above:
These properties all represent a collection of items. In order to populate these properties, we need to explicitly load the collection property:
We can now work with the collection of lists from the Web. Notice that we don’t need to load up the web object because we don’t access any of its properties, except the lists collection property, which we are explicitly loading.
If you don’t fill up a collection property and commit the batch before trying to access the collection property, you will get an error message that says The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.
Performance: Property/Column Values and RowLimit
- Listing the property names we need in the load statement
- Trimming our queries to retrieve only the columns we need
The latter is the same concept as what we’ve done using SPQuery for years, although the syntax is slightly different, as you’ll see in a moment. The former is new to CSOM. Unlike the load statements shown above which do not specify the properties we need, and therefore pull down all properties, a more efficient load statement would look like this:
This would limit the properties that are populated on our lists object to just the Title of each list and the DataSource. If you do limit the properties that are populated in this way, you need to make sure that you specify every property that you need. Similar to the error above if a collection property is not populated, if you attempt to access a scalar property that has not been populated, you will get an error The property or field has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.
The syntax for trimming the columns sent down to the client is similar to what we use on the server, but just slightly different syntactically:
You can see the way the ViewFields elements are set into the query, which is stored in the viewXml property of the CamlQuery object. This example will only retrieve the Title column value from the database and send it down the wire.
This example also shows how to limit the number of records that are sent down to the client. This is another important aspect of maintaining performance. In this example, the result set is limited to the first two records by use of the RowLimit element..
Examples of Real World Tasks
|NOTE: I wrote some of these samples for MSDN back during the beta of 2010 and some of them are available in the SDK, although I tweaked some of them a little and tested them all for this blog post.|
Get ListItem By ID
If you know the ID of a ListItem, this sample demonstrates how to retrieve it. It also demonstrates how to retrieve a List by name.
Submit a CAML Query
This sample shows you how to query a list using CAML and iterate through all items in a collection.
Paging Through a ListItemCollection
This sample pages through the items in a list two at a time, unlike the previous example which iterates through all items in the returned collection in one operation.
Retrieve a Web – #1
Retrieve a Web – #2
This sample shows how to retrieve a Web based on its server-relative URL. Note: the Web being retrieved must be in the same site collection.
Retrieve a Web – #3
This sample shows how to retrieve the site at the root of a site collection from a child web somewhere else in the site collection.
Additional Examples From the SDK
There’s a section in the SDK with some good examples of common tasks. Rather than completely reinvent the wheel, I’ll just link to them: