http://msdn.microsoft.com/en-us/library/ee857094(office.14).aspx
The SharePoint 2010 Client Object Model is a very cool feature of SharePoint 2010 Foundation Server that enables developers to write applications that access SharePoint data from a .NET application running on a client computer, from a Silverlight application, and from JavaScript running client-side in a SharePoint web part. The client object model enables this without requiring the developer to write or install code on the SharePoint server. The client object model makes it possible to build new categories of applications that integrate with Microsoft SharePoint Foundation 2010, including writing .NET applications, rich interactive web parts, and Silverlight applications.
I've written an MSDN article, Using the SharePoint 2010 Managed Client Object Model, that provides the basics on using the Client Object Model. Many thanks to Michael Cheng of the client object model team for technically reviewing the article, and providing me with many suggestions that improved it.
The article Using the SharePoint 2010 Client Object Model with the Open XML SDK 2.0provides additional information around uploading and downloading files from a document library, as well as examples that modify Open XML documents using the Open XML SDK.
The SharePoint 2010 Client Object Model is a very cool feature of SharePoint 2010 Foundation Server that enables developers to write applications that access SharePoint data from a .NET application running on a client computer, from a Silverlight application, and from JavaScript running client-side in a SharePoint web part. The client object model enables this without requiring the developer to write or install code on the SharePoint server. The client object model makes it possible to build new categories of applications that integrate with Microsoft SharePoint Foundation 2010, including writing .NET applications, rich interactive web parts, and Silverlight applications.
Using the SharePoint Foundation 2010 Managed Client Object Model
Summary: Learn how to use the SharePoint Foundation 2010 managed client object model to write applications that are based on the .NET Framework and access SharePoint content from clients without installing code on the server that runs SharePoint Foundation 2010.
Applies to: SharePoint Foundation 2010
Provided by: Eric White, Microsoft Corporation
Contents
- Overview
- Using the SharePoint Foundation 2010 Managed Client Object Model
- How the Client-Side Object Model Works
- Creating Windows Console Managed Client Object Model Applications
- Overview of the SharePoint Foundation 2010 Managed Client Object Model
- Using Object Identities
- Trimming Result Sets
- Creating and Populating a List
- Using CAML to Query Lists
- Filtering the Child Collection Returned by Load by Using LINQ
- Using the LoadQuery Method
- Increasing Performance by Nesting Include Statements in LoadQuery
- Filtering the Child Collection Returned by LoadQuery by Using LINQ
- Updating Client Objects
- Deleting Client Objects
- Discovering the Schema for Fields
- Accessing Large Lists
- Asynchronous Processing
- Additional Resources
Summary: Learn how to use the SharePoint Foundation 2010 managed client object model to write applications that are based on the .NET Framework and access SharePoint content from clients without installing code on the server that runs SharePoint Foundation 2010.
Applies to: SharePoint Foundation 2010
Provided by: Eric White, Microsoft Corporation
Contents
Provided by: Eric White, Microsoft Corporation
Contents
- Overview
- Using the SharePoint Foundation 2010 Managed Client Object Model
- How the Client-Side Object Model Works
- Creating Windows Console Managed Client Object Model Applications
- Overview of the SharePoint Foundation 2010 Managed Client Object Model
- Using Object Identities
- Trimming Result Sets
- Creating and Populating a List
- Using CAML to Query Lists
- Filtering the Child Collection Returned by Load by Using LINQ
- Using the LoadQuery Method
- Increasing Performance by Nesting Include Statements in LoadQuery
- Filtering the Child Collection Returned by LoadQuery by Using LINQ
- Updating Client Objects
- Deleting Client Objects
- Discovering the Schema for Fields
- Accessing Large Lists
- Asynchronous Processing
- Additional Resources
Overview
With the SharePoint Foundation 2010 managed client object model, you can design client applications that access SharePoint content without installing code on the server that runs Microsoft SharePoint Foundation 2010. For example, you can build new categories of applications that include writing applications that are based on the Microsoft .NET Framework, rich interactive Web Parts, Microsoft Silverlight applications, and ECMAScript (JavaScript, JScript) applications that run client-side in a SharePoint Web Part. For example:
- A team leader creates a SharePoint site that has many lists that are required to manage her team’s mission. She wants to change these lists in an ad-hoc manner—perhaps updating assignments and estimates based on an Open XML spreadsheet, or moving items from one SharePoint list to another. She wants to write a small custom application to help her manage this.
- A software company that sells a traditional rich client application wants to integrate SharePoint document libraries and lists into their application, and they want this integration to be seamless, or even invisible to their users.
- A SharePoint developer wants to build a rich Web Part for a SharePoint deployment that brings list content into their custom AJAX web code. He also wants to build an even richer Silverlight application that does the same thing.
What do these people have in common? They can use the SharePoint Foundation 2010 managed client object model to achieve their goals. The SharePoint Foundation 2010 managed client object model lets you write client-side code to work with all the common objects in SharePoint sites. Through the object model, you can add and remove lists, add, update, and delete list items, change documents in document libraries, create sites, manage permissions of items, and add and remove Web Parts from a page.
Previously, there were few options. You could use Web services to interact with SharePoint lists and other features, but this was challenging. If the Web services did not provide the necessary capabilities, you could write server-side code to provide a new Web service (an even more difficult task). Some IT departments disallow server-side code, or allow only code that is written by the IT department so that sometimes that was not an option. The SharePoint Foundation 2010 managed client object model enables new kinds of applications and makes it easier to write client-side code that interacts with SharePoint content.
With the SharePoint Foundation 2010 managed client object model, you can design client applications that access SharePoint content without installing code on the server that runs Microsoft SharePoint Foundation 2010. For example, you can build new categories of applications that include writing applications that are based on the Microsoft .NET Framework, rich interactive Web Parts, Microsoft Silverlight applications, and ECMAScript (JavaScript, JScript) applications that run client-side in a SharePoint Web Part. For example:
Previously, there were few options. You could use Web services to interact with SharePoint lists and other features, but this was challenging. If the Web services did not provide the necessary capabilities, you could write server-side code to provide a new Web service (an even more difficult task). Some IT departments disallow server-side code, or allow only code that is written by the IT department so that sometimes that was not an option. The SharePoint Foundation 2010 managed client object model enables new kinds of applications and makes it easier to write client-side code that interacts with SharePoint content.
- A team leader creates a SharePoint site that has many lists that are required to manage her team’s mission. She wants to change these lists in an ad-hoc manner—perhaps updating assignments and estimates based on an Open XML spreadsheet, or moving items from one SharePoint list to another. She wants to write a small custom application to help her manage this.
- A software company that sells a traditional rich client application wants to integrate SharePoint document libraries and lists into their application, and they want this integration to be seamless, or even invisible to their users.
- A SharePoint developer wants to build a rich Web Part for a SharePoint deployment that brings list content into their custom AJAX web code. He also wants to build an even richer Silverlight application that does the same thing.
Previously, there were few options. You could use Web services to interact with SharePoint lists and other features, but this was challenging. If the Web services did not provide the necessary capabilities, you could write server-side code to provide a new Web service (an even more difficult task). Some IT departments disallow server-side code, or allow only code that is written by the IT department so that sometimes that was not an option. The SharePoint Foundation 2010 managed client object model enables new kinds of applications and makes it easier to write client-side code that interacts with SharePoint content.
Using the SharePoint Foundation 2010 Managed Client Object Model
To use the SharePoint Foundation 2010 managed client object model (client object model), you write managed code based on the .NET Framework that uses an API that resembles the object model that is used on a server that is running SharePoint Foundation. The client object model has classes for accessing site collection information, site information, and list and list item information.
In the case of Web Parts, you use an ECMAScript (JavaScript, JScript) programming interface that resembles the .NET Framework API. For Silverlight, you use a subset of the API that is available through the .NET Framework on the client. Although much of the information that is presented in this article is relevant to the JavaScript and Silverlight APIs, this article focuses primarily about how to use the SharePoint Foundation 2010 managed client object model from a client application that is based on the .NET Framework.
The SharePoint Foundation 2010 managed client object model consists of two assemblies that contain five namespaces. If you look at the classes available in those namespaces, you see many classes. Do not worry; many of those classes are used internally by the object model. You are interested only in a subset of them, primarily classes that have direct counterparts to some familiar classes in the SharePoint Foundation server object model.
To use the SharePoint Foundation 2010 managed client object model (client object model), you write managed code based on the .NET Framework that uses an API that resembles the object model that is used on a server that is running SharePoint Foundation. The client object model has classes for accessing site collection information, site information, and list and list item information.
In the case of Web Parts, you use an ECMAScript (JavaScript, JScript) programming interface that resembles the .NET Framework API. For Silverlight, you use a subset of the API that is available through the .NET Framework on the client. Although much of the information that is presented in this article is relevant to the JavaScript and Silverlight APIs, this article focuses primarily about how to use the SharePoint Foundation 2010 managed client object model from a client application that is based on the .NET Framework.
The SharePoint Foundation 2010 managed client object model consists of two assemblies that contain five namespaces. If you look at the classes available in those namespaces, you see many classes. Do not worry; many of those classes are used internally by the object model. You are interested only in a subset of them, primarily classes that have direct counterparts to some familiar classes in the SharePoint Foundation server object model.
In the case of Web Parts, you use an ECMAScript (JavaScript, JScript) programming interface that resembles the .NET Framework API. For Silverlight, you use a subset of the API that is available through the .NET Framework on the client. Although much of the information that is presented in this article is relevant to the JavaScript and Silverlight APIs, this article focuses primarily about how to use the SharePoint Foundation 2010 managed client object model from a client application that is based on the .NET Framework.
The SharePoint Foundation 2010 managed client object model consists of two assemblies that contain five namespaces. If you look at the classes available in those namespaces, you see many classes. Do not worry; many of those classes are used internally by the object model. You are interested only in a subset of them, primarily classes that have direct counterparts to some familiar classes in the SharePoint Foundation server object model.
Table 1. Client-side classes and server-side equivalents
Client Server
ClientContext SPContext
Site SPSite
Web SPWeb
List SPList
ListItem SPListItem
Field SPField
Notice that the SharePoint Foundation 2010 managed client object model uses the same legacy naming pattern for site collections and sites as the server object model. The Site class represents site collections, and the Web class represents sites. My preference for using these classes is to name the variables so that the variable name indicates whether it is a site collection or a site, even though you must use the Siteand Web classes to declare them.
The following example shows how I name variables.
Client | Server |
---|---|
ClientContext | SPContext |
Site | SPSite |
Web | SPWeb |
List | SPList |
ListItem | SPListItem |
Field | SPField |
The following example shows how I name variables.
How the Client-Side Object Model Works
An application that uses SharePoint content interacts with the API in several ways—call methods and get the return values, pass a Collaborative Application Markup Language (CAML) query and get the results, and set or get properties. After you use the API to perform a specific task the SharePoint Foundation 2010 managed client object model bundles up these uses of the API into XML and sends it to the server that runs SharePoint Foundation. The server receives this request, and makes appropriate calls into the object model on the server, collects the responses, forms them into JavaScript Object Notation (JSON), and sends that JSON back to the SharePoint Foundation 2010 managed client object model. The client object model parses the JSON and presents the results to the application as .NET Framework objects (or JavaScript objects for JavaScript). The following diagram shows these interactions.
Figure 1. The SharePoint Foundation 2010 managed client object model
It is important to be aware that you control when the SharePoint Foundation 2010 managed client object model starts to send the XML to the server and receives the JSON back from the server.
The bundling of multiple method calls into a single call to the server is dictated by the realities of network speed, network latency, and desired performance characteristics. If the SharePoint Foundation 2010 managed client object model interacted with the server at every method call, the performance of the system, and the increased network traffic would make the system unworkable.
As I mentioned, you explicitly control when the SharePoint Foundation 2010 managed client object model bundles method calls and sends a request to the server. As part of this process, before you start the interaction with the server, you must explicitly specify what content that you want to retrieve from the server. This is the biggest difference between the SharePoint Foundation 2010 managed client object model and the SharePoint Foundation 2010 object model. But after you understand the model, it is not challenging. The easiest way to start understanding the difference is to see a simple application.
An application that uses SharePoint content interacts with the API in several ways—call methods and get the return values, pass a Collaborative Application Markup Language (CAML) query and get the results, and set or get properties. After you use the API to perform a specific task the SharePoint Foundation 2010 managed client object model bundles up these uses of the API into XML and sends it to the server that runs SharePoint Foundation. The server receives this request, and makes appropriate calls into the object model on the server, collects the responses, forms them into JavaScript Object Notation (JSON), and sends that JSON back to the SharePoint Foundation 2010 managed client object model. The client object model parses the JSON and presents the results to the application as .NET Framework objects (or JavaScript objects for JavaScript). The following diagram shows these interactions.
Figure 1. The SharePoint Foundation 2010 managed client object model
It is important to be aware that you control when the SharePoint Foundation 2010 managed client object model starts to send the XML to the server and receives the JSON back from the server.
The bundling of multiple method calls into a single call to the server is dictated by the realities of network speed, network latency, and desired performance characteristics. If the SharePoint Foundation 2010 managed client object model interacted with the server at every method call, the performance of the system, and the increased network traffic would make the system unworkable.
As I mentioned, you explicitly control when the SharePoint Foundation 2010 managed client object model bundles method calls and sends a request to the server. As part of this process, before you start the interaction with the server, you must explicitly specify what content that you want to retrieve from the server. This is the biggest difference between the SharePoint Foundation 2010 managed client object model and the SharePoint Foundation 2010 object model. But after you understand the model, it is not challenging. The easiest way to start understanding the difference is to see a simple application.
Figure 1. The SharePoint Foundation 2010 managed client object model
It is important to be aware that you control when the SharePoint Foundation 2010 managed client object model starts to send the XML to the server and receives the JSON back from the server.
The bundling of multiple method calls into a single call to the server is dictated by the realities of network speed, network latency, and desired performance characteristics. If the SharePoint Foundation 2010 managed client object model interacted with the server at every method call, the performance of the system, and the increased network traffic would make the system unworkable.
As I mentioned, you explicitly control when the SharePoint Foundation 2010 managed client object model bundles method calls and sends a request to the server. As part of this process, before you start the interaction with the server, you must explicitly specify what content that you want to retrieve from the server. This is the biggest difference between the SharePoint Foundation 2010 managed client object model and the SharePoint Foundation 2010 object model. But after you understand the model, it is not challenging. The easiest way to start understanding the difference is to see a simple application.
Creating Windows Console Managed Client Object Model Applications
Note:
I use Windows console applications for the sample code, but you can use the same approach with other application types.
To build the application, you must add references to two assemblies, Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll. Installing SharePoint Foundation installs these assemblies on the server. The two assemblies are located in the following directory:
%ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\ISAPI
Important:
For SharePoint Foundation Beta and Microsoft SharePoint Server 2010 Beta, you must copy the two assemblies and put them in a convenient location on your development client computer. You must browse to those assemblies to add references to them when you are setting up projects that use the SharePoint Foundation 2010 managed client object model.
Note: |
---|
I use Windows console applications for the sample code, but you can use the same approach with other application types. |
%ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\ISAPI
Important: |
---|
For SharePoint Foundation Beta and Microsoft SharePoint Server 2010 Beta, you must copy the two assemblies and put them in a convenient location on your development client computer. You must browse to those assemblies to add references to them when you are setting up projects that use the SharePoint Foundation 2010 managed client object model. |
To build the application
- Start Microsoft Visual Studio 2010.
- On the File menu, point to New, and then click Project.
- In the New Project dialog box, in the Recent Template pane, expand Visual C#, and then click Windows.
- To the right of the Recent Template pane, click Console Application.
- By default, Visual Studio creates a project that targets .NET Framework 4, but you must target .NET Framework 3.5. From the list at the upper part of the File Open dialog box, select .NET Framework 3.5.
- In the Name box, type the name that you want to use for your project, such asFirstClientApiApplication.
- In the Location box, type the location where you want to place the project.
Figure 2. Creating a solution in the New Project dialog box
- Click OK to create the solution.
- Start Microsoft Visual Studio 2010.
- On the File menu, point to New, and then click Project.
- In the New Project dialog box, in the Recent Template pane, expand Visual C#, and then click Windows.
- To the right of the Recent Template pane, click Console Application.
- By default, Visual Studio creates a project that targets .NET Framework 4, but you must target .NET Framework 3.5. From the list at the upper part of the File Open dialog box, select .NET Framework 3.5.
- In the Name box, type the name that you want to use for your project, such asFirstClientApiApplication.
- In the Location box, type the location where you want to place the project.
Figure 2. Creating a solution in the New Project dialog box - Click OK to create the solution.
To add references to the Microsoft.SharePoint.Client assembly and Microsoft.SharePoint.Client.Runtime assembly
- The classes that you use in a client object model application are located in Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll. As I mentioned, before you add the references, you must copy those assemblies from the server that runs SharePoint Foundation to the client development computer.
- On the Project menu, click Add Reference to open the Add Reference dialog box.
- Select the Browse tab, navigate to the location where you put the Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll. Select both DLLs, and then click OK as shown in Figure 3.
Figure 3. Adding references to the assemblies
- The classes that you use in a client object model application are located in Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll. As I mentioned, before you add the references, you must copy those assemblies from the server that runs SharePoint Foundation to the client development computer.
- On the Project menu, click Add Reference to open the Add Reference dialog box.
- Select the Browse tab, navigate to the location where you put the Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll. Select both DLLs, and then click OK as shown in Figure 3.
Figure 3. Adding references to the assemblies
To add the sample code to the solution
- In Visual Studio, replace the contents of the Program.cs source file with the following code.
using System;
using Microsoft.SharePoint.Client;
class DisplayWebTitle
{
static void Main()
{
ClientContext clientContext = new ClientContext("http://intranet.contoso.com");
Web site = clientContext.Web;
clientContext.Load(site);
clientContext.ExecuteQuery();
Console.WriteLine("Title: {0}", site.Title);
}
}
- Replace the URL in the ClientContext constructor with the URL to the SharePoint site. Build and run the solution. The example prints the title of the site.
Just as with the SharePoint Foundation server object model, you create a context for the SharePoint site that you want to access. You can then retrieve a reference to the site from the context.
The call to the ExecuteQuery method causes the SharePoint Foundation 2010 managed client object model to send the request to the server. There is no network traffic until the application calls the ExecuteQuery method.
An important point to make about this example is that the call to the Load method does not actually load anything. Instead, it informs the client object model that when the application calls the ExecuteQuery method, you want to load the property values of the siteCollection object.
This is the model that all interactions with the server take:
- You inform the SharePoint Foundation 2010 managed client object model about the operations that you want to take. This includes accessing the values of properties of objects (for example, objects of the List class, ListItem class, andWeb class), CAML queries that you want to run, and objects such as ListItemobjects that you want to insert, update or delete.
- Then you call the ExecuteQuery method. No network traffic occurs until you call the ExecuteQuery method. Until that point, your application is only registering its requests.
As you can see from this example, at its simplest, you first set up a query, and then you execute the queries. This causes the client object model to send traffic to the server and receive a response from it. This next section reviews the model in detail and shows why it is designed the way it is, and finally, how you can build applications by using the model.
- In Visual Studio, replace the contents of the Program.cs source file with the following code.
using System; using Microsoft.SharePoint.Client; class DisplayWebTitle { static void Main() { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); Web site = clientContext.Web; clientContext.Load(site); clientContext.ExecuteQuery(); Console.WriteLine("Title: {0}", site.Title); } }
- Replace the URL in the ClientContext constructor with the URL to the SharePoint site. Build and run the solution. The example prints the title of the site.
The call to the ExecuteQuery method causes the SharePoint Foundation 2010 managed client object model to send the request to the server. There is no network traffic until the application calls the ExecuteQuery method.
An important point to make about this example is that the call to the Load method does not actually load anything. Instead, it informs the client object model that when the application calls the ExecuteQuery method, you want to load the property values of the siteCollection object.
This is the model that all interactions with the server take:
- You inform the SharePoint Foundation 2010 managed client object model about the operations that you want to take. This includes accessing the values of properties of objects (for example, objects of the List class, ListItem class, andWeb class), CAML queries that you want to run, and objects such as ListItemobjects that you want to insert, update or delete.
- Then you call the ExecuteQuery method. No network traffic occurs until you call the ExecuteQuery method. Until that point, your application is only registering its requests.
Overview of the SharePoint Foundation 2010 Managed Client Object Model
There are specific aspects of the client object model that you must examine:
- Approaches that the client object model takes to minimize network traffic
- Query construction
- Techniques to improve server performance
- How to create, update, and delete client objects
- How to work with very large lists
Before we delve into any of these subjects, let's examine the issue of object identity.
There are specific aspects of the client object model that you must examine:
- Approaches that the client object model takes to minimize network traffic
- Query construction
- Techniques to improve server performance
- How to create, update, and delete client objects
- How to work with very large lists
Using Object Identities
The key idea behind object identity is that client objects refer to the corresponding in the SharePoint Foundation server object model both before and after they call theExecuteQuery method. They continue to refer to that same object through multiple calls to the ExecuteQuery method.
This means that when setting up the query, the client object model returns objects that you can use to further set up the query before you call the ExecuteQuerymethod. This lets you to write more complex queries before you start causing traffic to and from the server. You can do more interesting things in a single query, and eliminate network traffic.
The following example gets the Announcements list object, and then it retrieves all items of that list by using the simplest possible CAML query.
using System;
using Microsoft.SharePoint.Client;
class Program
{
static void Main()
{
ClientContext clientContext = new ClientContext("http://intranet.contoso.com");
List list = clientContext.Web.Lists.GetByTitle("Announcements");
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View/>";
ListItemCollection listItems = list.GetItems(camlQuery);
clientContext.Load(list);clientContext.Load(listItems);
clientContext.ExecuteQuery();
foreach (ListItem listItem in listItems)
Console.WriteLine("Id: {0} Title: {1}", listItem.Id, oListItem["Title"]);
}
}
Notice the sequence in this example:
- First the code gets a List object by using the GetByTitle method. Remember, this List object has no data in it; it does not have data in any of its properties until the application calls the ExecuteQuery method.
- It then calls the GetItems method on the list object, even though that list object is not populated with data.
- It finally calls the Load method on both the list object and listItems object, and then calls the ExecuteQuery method.
The key point about this is that the client object model remembers that the list object is the one that the application initialized by using the GetByTitle method, and that the client object model should execute the CAML query on that same list object after thelist object is retrieved from the SharePoint database. Any class that derives from theClientObject class has these semantics.
And, as mentioned, you can continue to use client objects to set up additional queries after you call the ExecuteQuery method. In the following example, the code loads thelist object and calls the ExecuteQuery method. It then uses that list client object to call the List.GetItems method, and then calls the ExecuteQuery method again. Thelist object retained its identity through the call to ExecuteQuery method.
using System;
using Microsoft.SharePoint.Client;
class Program
{
static void Main()
{
ClientContext clientContext =
new ClientContext("http://intranet.contoso.com");
List list = clientContext.Web.Lists
.GetByTitle("Announcements");
clientContext.Load(list);
clientContext.ExecuteQuery();
Console.WriteLine("List Title: {0}", list.Title);
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View/>";
ListItemCollection listItems = list.GetItems(camlQuery);
clientContext.Load(listItems);
clientContext.ExecuteQuery();
foreach (ListItem listItem in listItems)
Console.WriteLine("Id: {0} Title: {1}",
oListItem.Id, listItem["Title"]);
}
}
Some properties and methods return objects or value types that do not derive from theClientObject class. You benefit from using client object identity to access methods and properties only when those methods and properties return client objects or collections of them. For instance, some classes, such as the FieldUrlValue class and the FieldLookupValue class derive from the ClientValueObject class, and you cannot use properties that return those types until after the call to the ExecuteQuerymethod. Some properties return .NET Framework types such as string or integer, and you also cannot use properties or methods that return those until after the call to theExecuteQuery method. Because you cannot use the values of any properties until those values are populated in the ExecuteQuery call, you cannot, for example, find an item in a list, and use the value of one of that item’s fields to select items in an additional query. If you try to use a property before it is populated by theExecuteQuery method, the client object model throws aPropertyOrFieldNotInitializedException exception.
Caution:
Client object identity is valid only for a single ClientContext object. If you initialize another ClientContext object to the same SharePoint site, you cannot use client objects from one client context with the other one.
A number of later examples in this article use object identity behavior.
Note:
This example does not do any error handling. If the Announcements list does not exist, the client object model throws an exception in the call to the ExecuteQuerymethod. You should be prepared to catch exceptions when you write code that may fail if you ask for objects that may not exist.
The key idea behind object identity is that client objects refer to the corresponding in the SharePoint Foundation server object model both before and after they call theExecuteQuery method. They continue to refer to that same object through multiple calls to the ExecuteQuery method.
This means that when setting up the query, the client object model returns objects that you can use to further set up the query before you call the ExecuteQuerymethod. This lets you to write more complex queries before you start causing traffic to and from the server. You can do more interesting things in a single query, and eliminate network traffic.
The following example gets the Announcements list object, and then it retrieves all items of that list by using the simplest possible CAML query.
Notice the sequence in this example:
And, as mentioned, you can continue to use client objects to set up additional queries after you call the ExecuteQuery method. In the following example, the code loads thelist object and calls the ExecuteQuery method. It then uses that list client object to call the List.GetItems method, and then calls the ExecuteQuery method again. Thelist object retained its identity through the call to ExecuteQuery method.
Some properties and methods return objects or value types that do not derive from theClientObject class. You benefit from using client object identity to access methods and properties only when those methods and properties return client objects or collections of them. For instance, some classes, such as the FieldUrlValue class and the FieldLookupValue class derive from the ClientValueObject class, and you cannot use properties that return those types until after the call to the ExecuteQuerymethod. Some properties return .NET Framework types such as string or integer, and you also cannot use properties or methods that return those until after the call to theExecuteQuery method. Because you cannot use the values of any properties until those values are populated in the ExecuteQuery call, you cannot, for example, find an item in a list, and use the value of one of that item’s fields to select items in an additional query. If you try to use a property before it is populated by theExecuteQuery method, the client object model throws aPropertyOrFieldNotInitializedException exception.
A number of later examples in this article use object identity behavior.
This means that when setting up the query, the client object model returns objects that you can use to further set up the query before you call the ExecuteQuerymethod. This lets you to write more complex queries before you start causing traffic to and from the server. You can do more interesting things in a single query, and eliminate network traffic.
The following example gets the Announcements list object, and then it retrieves all items of that list by using the simplest possible CAML query.
using System; using Microsoft.SharePoint.Client; class Program { static void Main() { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); List list = clientContext.Web.Lists.GetByTitle("Announcements"); CamlQuery camlQuery = new CamlQuery(); camlQuery.ViewXml = "<View/>"; ListItemCollection listItems = list.GetItems(camlQuery); clientContext.Load(list);clientContext.Load(listItems); clientContext.ExecuteQuery(); foreach (ListItem listItem in listItems) Console.WriteLine("Id: {0} Title: {1}", listItem.Id, oListItem["Title"]); } }
- First the code gets a List object by using the GetByTitle method. Remember, this List object has no data in it; it does not have data in any of its properties until the application calls the ExecuteQuery method.
- It then calls the GetItems method on the list object, even though that list object is not populated with data.
- It finally calls the Load method on both the list object and listItems object, and then calls the ExecuteQuery method.
And, as mentioned, you can continue to use client objects to set up additional queries after you call the ExecuteQuery method. In the following example, the code loads thelist object and calls the ExecuteQuery method. It then uses that list client object to call the List.GetItems method, and then calls the ExecuteQuery method again. Thelist object retained its identity through the call to ExecuteQuery method.
using System; using Microsoft.SharePoint.Client; class Program { static void Main() { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); List list = clientContext.Web.Lists .GetByTitle("Announcements"); clientContext.Load(list); clientContext.ExecuteQuery(); Console.WriteLine("List Title: {0}", list.Title); CamlQuery camlQuery = new CamlQuery(); camlQuery.ViewXml = "<View/>"; ListItemCollection listItems = list.GetItems(camlQuery); clientContext.Load(listItems); clientContext.ExecuteQuery(); foreach (ListItem listItem in listItems) Console.WriteLine("Id: {0} Title: {1}", oListItem.Id, listItem["Title"]); } }
Caution: |
---|
Client object identity is valid only for a single ClientContext object. If you initialize another ClientContext object to the same SharePoint site, you cannot use client objects from one client context with the other one. |
Note: |
---|
This example does not do any error handling. If the Announcements list does not exist, the client object model throws an exception in the call to the ExecuteQuerymethod. You should be prepared to catch exceptions when you write code that may fail if you ask for objects that may not exist. |
Trimming Result Sets
SharePoint Foundation is often deployed in organizations with many thousands of users. When building an application that accesses SharePoint Foundation over the network, it makes sense to build it so that it uses the least amount of network traffic. There are several ways that the client object model helps you do this. The simplest approach is to use lambda expressions to specify exactly which properties the client object model should return to the application.
The following example shows how to specify that when the client object model loads the site object, it must load only the Title property and Description property. This reduces the size of the JSON response from the server back to the client.
using System;
using Microsoft.SharePoint.Client;
class Program
{
static void Main()
{
ClientContext clientContext =
new ClientContext("http://intranet.contoso.com");
Web site = clientContext.Web;
clientContext.Load(site,
s => s.Title,
s => s.Description);
clientContext.ExecuteQuery();
Console.WriteLine("Title: {0} Description: {1}",
site.Title, site.Description);
}
}
By default, if you do not include these lambda expressions in the call to the Loadmethod, it loads a much larger number of properties (but not them all). The first two examples called the Load method without specifying which properties to load, so that the JSON packet that the server returned was somewhat larger than it needed to be. Although in these small examples, it does not make much difference, when it loads thousands of list items, carefully specifying the required properties reduces network traffic.
Using lambda expressions, you can specify a list of properties to the Load method. Reducing network traffic is not the only benefit you derive from the client object model’s use of lambda expressions. Later on this article describes how to filter result sets using lambda expressions.
Next, I’ll show an example that creates a list and then add some content to it. This will provide sample content to work with for the rest of this article.
SharePoint Foundation is often deployed in organizations with many thousands of users. When building an application that accesses SharePoint Foundation over the network, it makes sense to build it so that it uses the least amount of network traffic. There are several ways that the client object model helps you do this. The simplest approach is to use lambda expressions to specify exactly which properties the client object model should return to the application.
The following example shows how to specify that when the client object model loads the site object, it must load only the Title property and Description property. This reduces the size of the JSON response from the server back to the client.
By default, if you do not include these lambda expressions in the call to the Loadmethod, it loads a much larger number of properties (but not them all). The first two examples called the Load method without specifying which properties to load, so that the JSON packet that the server returned was somewhat larger than it needed to be. Although in these small examples, it does not make much difference, when it loads thousands of list items, carefully specifying the required properties reduces network traffic.
Using lambda expressions, you can specify a list of properties to the Load method. Reducing network traffic is not the only benefit you derive from the client object model’s use of lambda expressions. Later on this article describes how to filter result sets using lambda expressions.
Next, I’ll show an example that creates a list and then add some content to it. This will provide sample content to work with for the rest of this article.
The following example shows how to specify that when the client object model loads the site object, it must load only the Title property and Description property. This reduces the size of the JSON response from the server back to the client.
using System; using Microsoft.SharePoint.Client; class Program { static void Main() { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); Web site = clientContext.Web; clientContext.Load(site, s => s.Title, s => s.Description); clientContext.ExecuteQuery(); Console.WriteLine("Title: {0} Description: {1}", site.Title, site.Description); } }
Using lambda expressions, you can specify a list of properties to the Load method. Reducing network traffic is not the only benefit you derive from the client object model’s use of lambda expressions. Later on this article describes how to filter result sets using lambda expressions.
Next, I’ll show an example that creates a list and then add some content to it. This will provide sample content to work with for the rest of this article.
Creating and Populating a List
The following example creates a list, and adds some fields and several items to it.
using System;
using Microsoft.SharePoint.Client;
class Program
{
static void Main()
{
ClientContext clientContext =
new ClientContext("http://intranet.contoso.com");
Web site = clientContext.Web;
// Create a list.
ListCreationInformation listCreationInfo =
new ListCreationInformation();
listCreationInfo.Title = "Client API Test List";
listCreationInfo.TemplateType = (int)ListTemplateType.GenericList;
List list = site.Lists.Add(listCreationInfo);
// Add fields to the list.
Field field1 = list.Fields.AddFieldAsXml(
@"<Field Type='Choice'
DisplayName='Category'
Format='Dropdown'>
<Default>Specification</Default>
<CHOICES>
<CHOICE>Specification</CHOICE>
<CHOICE>Development</CHOICE>
<CHOICE>Test</CHOICE>
<CHOICE>Documentation</CHOICE>
</CHOICES>
</Field>",
true, AddFieldOptions.DefaultValue);
Field field2 = list.Fields.AddFieldAsXml(
@"<Field Type='Number'
DisplayName='Estimate'/>",
true, AddFieldOptions.DefaultValue);
// Add some data.
ListItemCreationInformation itemCreateInfo =
new ListItemCreationInformation();
ListItem listItem = list.AddItem(itemCreateInfo);
listItem["Title"] = "Write specs for user interface.";
listItem["Category"] = "Specification";
listItem["Estimate"] = "20";
listItem.Update();
listItem = list.AddItem(itemCreateInfo);
listItem["Title"] = "Develop proof-of-concept.";
listItem["Category"] = "Development";
listItem["Estimate"] = "42";
listItem.Update();
listItem = list.AddItem(itemCreateInfo);
listItem["Title"] = "Write test plan for user interface.";
listItem["Category"] = "Test";
listItem["Estimate"] = "16";
listItem.Update();
listItem = list.AddItem(itemCreateInfo);
listItem["Title"] = "Validate SharePoint interaction.";
listItem["Category"] = "Test";
listItem["Estimate"] = "18";
listItem.Update();
listItem = list.AddItem(itemCreateInfo);
listItem["Title"] = "Develop user interface.";
listItem["Category"] = "Development";
listItem["Estimate"] = "18";
listItem.Update();
clientContext.ExecuteQuery();
}
}
In many cases, where you can create a client object, the application can call an Addmethod that takes as an argument an object that specifies creation information. This example shows how to use ListCreationInformation class to create a List object, and how to use the ListItemCreationInformation class for creating a ListItem object. You often set properties of the creation information class after instantiating it. You can see that the code sets the Title property and TemplateType property of theListItemCreationInformation object. Note that to create a list, you call the Addmethod, but to create a ListItem object, you call the AddItem method. The Addmethod creates a list in the collection, and the AddItem method creates a single list item.
Creating fields in a list also does not use an Add method, because, when you create fields, you are not really creating an instance of the Field class. You are creating an instance of a class that derives from the Field class. There are many options available for those derived classes, and using an Add method would significantly complicate the design of a FieldCreationInformation class. For this reason, the client object model does not include such a class. Instead, the simplest way to create a field is to specify a bit of XML that defines the field, and pass that XML to the AddFieldAsXmlmethod. There is a Add method that you can use to create a field, but instead of taking a FieldCreationInformation object, it takes another Field object as a parameter that it uses as a prototype for the field to be created. This is useful in some scenarios.
Tip:
The Discovering the Schema for Fields section of this article shows you an easy way to discover the XML that you must specify for fields that you want to create.
Note that, of course, no objects are actually added to the SharePoint database until the application calls the ExecuteQuery method.
There is one more item of interest in this example. Notice that after you call theAddItem method, the example sets three indexed properties. The code is setting the values of the fields that were previously added to the list. After setting these properties, the application must call the Update method, informing the client object model that those objects were modified. The client object model does not work correctly if you do not do so. You see the Update method used in later examples, when I show how to modify existing client objects.
Now that you have some data, let us discover some interesting ways to query and change it.
The following example creates a list, and adds some fields and several items to it.
In many cases, where you can create a client object, the application can call an Addmethod that takes as an argument an object that specifies creation information. This example shows how to use ListCreationInformation class to create a List object, and how to use the ListItemCreationInformation class for creating a ListItem object. You often set properties of the creation information class after instantiating it. You can see that the code sets the Title property and TemplateType property of theListItemCreationInformation object. Note that to create a list, you call the Addmethod, but to create a ListItem object, you call the AddItem method. The Addmethod creates a list in the collection, and the AddItem method creates a single list item.
Creating fields in a list also does not use an Add method, because, when you create fields, you are not really creating an instance of the Field class. You are creating an instance of a class that derives from the Field class. There are many options available for those derived classes, and using an Add method would significantly complicate the design of a FieldCreationInformation class. For this reason, the client object model does not include such a class. Instead, the simplest way to create a field is to specify a bit of XML that defines the field, and pass that XML to the AddFieldAsXmlmethod. There is a Add method that you can use to create a field, but instead of taking a FieldCreationInformation object, it takes another Field object as a parameter that it uses as a prototype for the field to be created. This is useful in some scenarios.
Note that, of course, no objects are actually added to the SharePoint database until the application calls the ExecuteQuery method.
There is one more item of interest in this example. Notice that after you call theAddItem method, the example sets three indexed properties. The code is setting the values of the fields that were previously added to the list. After setting these properties, the application must call the Update method, informing the client object model that those objects were modified. The client object model does not work correctly if you do not do so. You see the Update method used in later examples, when I show how to modify existing client objects.
Now that you have some data, let us discover some interesting ways to query and change it.
using System; using Microsoft.SharePoint.Client; class Program { static void Main() { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); Web site = clientContext.Web; // Create a list. ListCreationInformation listCreationInfo = new ListCreationInformation(); listCreationInfo.Title = "Client API Test List"; listCreationInfo.TemplateType = (int)ListTemplateType.GenericList; List list = site.Lists.Add(listCreationInfo); // Add fields to the list. Field field1 = list.Fields.AddFieldAsXml( @"<Field Type='Choice' DisplayName='Category' Format='Dropdown'> <Default>Specification</Default> <CHOICES> <CHOICE>Specification</CHOICE> <CHOICE>Development</CHOICE> <CHOICE>Test</CHOICE> <CHOICE>Documentation</CHOICE> </CHOICES> </Field>", true, AddFieldOptions.DefaultValue); Field field2 = list.Fields.AddFieldAsXml( @"<Field Type='Number' DisplayName='Estimate'/>", true, AddFieldOptions.DefaultValue); // Add some data. ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation(); ListItem listItem = list.AddItem(itemCreateInfo); listItem["Title"] = "Write specs for user interface."; listItem["Category"] = "Specification"; listItem["Estimate"] = "20"; listItem.Update(); listItem = list.AddItem(itemCreateInfo); listItem["Title"] = "Develop proof-of-concept."; listItem["Category"] = "Development"; listItem["Estimate"] = "42"; listItem.Update(); listItem = list.AddItem(itemCreateInfo); listItem["Title"] = "Write test plan for user interface."; listItem["Category"] = "Test"; listItem["Estimate"] = "16"; listItem.Update(); listItem = list.AddItem(itemCreateInfo); listItem["Title"] = "Validate SharePoint interaction."; listItem["Category"] = "Test"; listItem["Estimate"] = "18"; listItem.Update(); listItem = list.AddItem(itemCreateInfo); listItem["Title"] = "Develop user interface."; listItem["Category"] = "Development"; listItem["Estimate"] = "18"; listItem.Update(); clientContext.ExecuteQuery(); } }
Creating fields in a list also does not use an Add method, because, when you create fields, you are not really creating an instance of the Field class. You are creating an instance of a class that derives from the Field class. There are many options available for those derived classes, and using an Add method would significantly complicate the design of a FieldCreationInformation class. For this reason, the client object model does not include such a class. Instead, the simplest way to create a field is to specify a bit of XML that defines the field, and pass that XML to the AddFieldAsXmlmethod. There is a Add method that you can use to create a field, but instead of taking a FieldCreationInformation object, it takes another Field object as a parameter that it uses as a prototype for the field to be created. This is useful in some scenarios.
Tip: |
---|
The Discovering the Schema for Fields section of this article shows you an easy way to discover the XML that you must specify for fields that you want to create. |
There is one more item of interest in this example. Notice that after you call theAddItem method, the example sets three indexed properties. The code is setting the values of the fields that were previously added to the list. After setting these properties, the application must call the Update method, informing the client object model that those objects were modified. The client object model does not work correctly if you do not do so. You see the Update method used in later examples, when I show how to modify existing client objects.
Now that you have some data, let us discover some interesting ways to query and change it.
Using CAML to Query Lists
The following example shows how to use CAML to query the list that you created in the last example. This example prints the Development items from our test list.
using System;
using Microsoft.SharePoint.Client;
class Program
{
static void Main(string[] args)
{
ClientContext clientContext = new ClientContext("http://intranet.contoso.com");
List list = clientContext.Web.Lists.GetByTitle("Client API Test List");
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml =
@"<View>
<Query>
<Where>
<Eq>
<FieldRef Name='Category'/>
<Value Type='Text'>Development</Value>
</Eq>
</Where>
</Query>
<RowLimit>100</RowLimit>
</View>";
ListItemCollection listItems = list.GetItems(camlQuery);
clientContext.Load(
listItems,
items => items
.Include(
item => item["Title"],
item => item["Category"],
item => item["Estimate"]));
clientContext.ExecuteQuery();
foreach (ListItem listItem in listItems)
{
Console.WriteLine("Title: {0}", listItem["Title"]);
Console.WriteLine("Category: {0}", listItem["Category"]);
Console.WriteLine("Estimate: {0}", listItem["Estimate"]);
Console.WriteLine();
}
}
}
This example produces the following output.
Title: Develop proof-of-concept.
Category: Development
Estimate: 42
Title: Develop user interface.
Category: Development
Estimate: 18
You may notice a difference between the lambda expressions that you specify in this example and the lambda expressions in the example that is presented in theTrimming Result Sets section. You must use the Include extension method to specify the properties that you want to load for each item in the collection that we load. Theitems parameter of the lambda expression is of type ListItemCollection, which of course does not contain an indexed property that allows us to specify which properties to load for items in the collection. Instead, you call the Include extension method, which enables us to specify which parameters of that child collection to load. Parameters to lambda expressions in the Include extension method are of the type of the items of the collection. Therefore, you can specify the properties that you want to load for each item in the collection.
Again, it is not completely necessary to understand the exact semantics of this use of lambda expressions. Just remember two coding idioms:
If you are requesting that the client object model load certain properties of a client object (not a collection of them), then specify the properties in the lambda expression that you add directly in the Load method.
If you are requesting that the client object model load certain properties of each item in a collection of client objects, use the Include extension method, and pass the lambda expressions that specify your desired properties to the Include method.
The following example shows how to use CAML to query the list that you created in the last example. This example prints the Development items from our test list.
This example produces the following output.
You may notice a difference between the lambda expressions that you specify in this example and the lambda expressions in the example that is presented in theTrimming Result Sets section. You must use the Include extension method to specify the properties that you want to load for each item in the collection that we load. Theitems parameter of the lambda expression is of type ListItemCollection, which of course does not contain an indexed property that allows us to specify which properties to load for items in the collection. Instead, you call the Include extension method, which enables us to specify which parameters of that child collection to load. Parameters to lambda expressions in the Include extension method are of the type of the items of the collection. Therefore, you can specify the properties that you want to load for each item in the collection.
Again, it is not completely necessary to understand the exact semantics of this use of lambda expressions. Just remember two coding idioms:
If you are requesting that the client object model load certain properties of a client object (not a collection of them), then specify the properties in the lambda expression that you add directly in the Load method.
If you are requesting that the client object model load certain properties of each item in a collection of client objects, use the Include extension method, and pass the lambda expressions that specify your desired properties to the Include method.
using System; using Microsoft.SharePoint.Client; class Program { static void Main(string[] args) { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); List list = clientContext.Web.Lists.GetByTitle("Client API Test List"); CamlQuery camlQuery = new CamlQuery(); camlQuery.ViewXml = @"<View> <Query> <Where> <Eq> <FieldRef Name='Category'/> <Value Type='Text'>Development</Value> </Eq> </Where> </Query> <RowLimit>100</RowLimit> </View>"; ListItemCollection listItems = list.GetItems(camlQuery); clientContext.Load( listItems, items => items .Include( item => item["Title"], item => item["Category"], item => item["Estimate"])); clientContext.ExecuteQuery(); foreach (ListItem listItem in listItems) { Console.WriteLine("Title: {0}", listItem["Title"]); Console.WriteLine("Category: {0}", listItem["Category"]); Console.WriteLine("Estimate: {0}", listItem["Estimate"]); Console.WriteLine(); } } }
Title: Develop proof-of-concept. Category: Development Estimate: 42 Title: Develop user interface. Category: Development Estimate: 18
Again, it is not completely necessary to understand the exact semantics of this use of lambda expressions. Just remember two coding idioms:
If you are requesting that the client object model load certain properties of a client object (not a collection of them), then specify the properties in the lambda expression that you add directly in the Load method.
If you are requesting that the client object model load certain properties of each item in a collection of client objects, use the Include extension method, and pass the lambda expressions that specify your desired properties to the Include method.
Filtering the Child Collection Returned by Load by Using LINQ
Because the Include extension method returns IQueryable<T>, you can chain from the Include method into the IQueryable<T>.Where extension method. This provides a succinct way to filter the result set. You should only use this capability when querying client object collections other than collections of ListItem objects, because while you could use this technique to filter collections of ListItem objects, using CAML results in better performance. This is important enough to say again:
Caution:
Never use the IQueryable<T>.Where extension method when querying ListItemobjects. The reason is that the client object model first evaluates the result of the CAML query, retrieves the results, and then filters the resulting collection using LINQ. If you filter a very large list using LINQ instead of CAML, the client object model attempts to retrieve all items in the list before filtering with LINQ and either issues queries that require too much system resources, or the query fails. The reason is not clear unless you know how the client object model works internally. You mustuse CAML when querying list items.
The following example queries the client object model for all lists that are not hidden. Notice that you must include a using directive for the System.Linq namespace.
using System;
using System.Linq;
using Microsoft.SharePoint.Client;
class Program
{
static void Main(string[] args)
{
ClientContext clientContext =
new ClientContext("http://intranet.contoso.com");
ListCollection listCollection = clientContext.Web.Lists;
clientContext.Load(
listCollection,
lists => lists
.Include(
list => list.Title,
list => list.Hidden)
. Where(list => ! list.Hidden)
);
clientContext.ExecuteQuery();
foreach (var list in listCollection)
Console.WriteLine(list.Title);
}
}
On my server, this example produces the following output.
Announcements
Calendar
Client API Test List
Content and Structure Reports
Customized Reports
Eric's ToDo List
Eric's Wiki
Form Templates
Links
Reusable Content
Shared Documents
Site Assets
Site Collection Documents
Site Collection Images
Site Pages
Style Library
Tasks
Team Discussion
Workflow Tasks
Because the Include extension method returns IQueryable<T>, you can chain from the Include method into the IQueryable<T>.Where extension method. This provides a succinct way to filter the result set. You should only use this capability when querying client object collections other than collections of ListItem objects, because while you could use this technique to filter collections of ListItem objects, using CAML results in better performance. This is important enough to say again:
The following example queries the client object model for all lists that are not hidden. Notice that you must include a using directive for the System.Linq namespace.
On my server, this example produces the following output.
Caution: |
---|
Never use the IQueryable<T>.Where extension method when querying ListItemobjects. The reason is that the client object model first evaluates the result of the CAML query, retrieves the results, and then filters the resulting collection using LINQ. If you filter a very large list using LINQ instead of CAML, the client object model attempts to retrieve all items in the list before filtering with LINQ and either issues queries that require too much system resources, or the query fails. The reason is not clear unless you know how the client object model works internally. You mustuse CAML when querying list items. |
using System; using System.Linq; using Microsoft.SharePoint.Client; class Program { static void Main(string[] args) { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); ListCollection listCollection = clientContext.Web.Lists; clientContext.Load( listCollection, lists => lists .Include( list => list.Title, list => list.Hidden) . Where(list => ! list.Hidden) ); clientContext.ExecuteQuery(); foreach (var list in listCollection) Console.WriteLine(list.Title); } }
Announcements Calendar Client API Test List Content and Structure Reports Customized Reports Eric's ToDo List Eric's Wiki Form Templates Links Reusable Content Shared Documents Site Assets Site Collection Documents Site Collection Images Site Pages Style Library Tasks Team Discussion Workflow Tasks
Using the LoadQuery Method
The LoadQuery method is similar in functionality to the Load method, except that in certain circumstances, the client object model can process the queries more efficiently and use memory more efficiently. It also allows for a more flexible programming style.
The LoadQuery method has different semantics than the Load method. Whereas theLoad method populates the client object (or client object collection) with data from the server, the LoadQuery method populates and returns a new collection. This means that you can query the same object collection multiple times and keep separate result sets for each query. For instance, you can query for all items in a project list that are assigned to a certain person, and separately query for all items that have an estimated hours that is larger than a certain threshold, and access both result sets at the same time. It also enables you to let these collections go out of scope, and thereby become eligible for garbage collection. Collections that you load using the Load method are eligible for garbage collection only when the client context variable itself goes out of scope. Other than these differences, the LoadQuerymethod provides the same functionality as the Load method.
The following example uses the LoadQuery method to retrieve a list of all the lists in the site.
using System;
using System.Collections.Generic;
using Microsoft.SharePoint.Client;
class Program
{
static void Main(string[] args)
{
ClientContext clientContext =
new ClientContext("http://intranet.contoso.com");
Web site = clientContext.Web;
ListCollection lists = site.Lists;
IEnumerable<List> newListCollection = clientContext.LoadQuery(
lists.Include(
list => list.Title,
list => list.Id,
list => list.Hidden));
clientContext.ExecuteQuery();
foreach (List list in newListCollection)
Console.WriteLine("Title: {0} Id: {1}",
list.Title.PadRight(40), list.Id.ToString("D"));
}
}
Notice that the LoadQuery method returns a new list collection that you can iterate through. The new list collection has a type of IEnumerable<List> instead ofListCollection.
There is one aspect of the semantics of the LoadQuery method that you must pay attention to. In the previous example, the original lists variable does not have its property values populated after the ExecuteQuery method returns. If you want that list to be populated, you must explicitly call the Load method, specifying which properties that you want loaded.
The LoadQuery method is similar in functionality to the Load method, except that in certain circumstances, the client object model can process the queries more efficiently and use memory more efficiently. It also allows for a more flexible programming style.
The LoadQuery method has different semantics than the Load method. Whereas theLoad method populates the client object (or client object collection) with data from the server, the LoadQuery method populates and returns a new collection. This means that you can query the same object collection multiple times and keep separate result sets for each query. For instance, you can query for all items in a project list that are assigned to a certain person, and separately query for all items that have an estimated hours that is larger than a certain threshold, and access both result sets at the same time. It also enables you to let these collections go out of scope, and thereby become eligible for garbage collection. Collections that you load using the Load method are eligible for garbage collection only when the client context variable itself goes out of scope. Other than these differences, the LoadQuerymethod provides the same functionality as the Load method.
The following example uses the LoadQuery method to retrieve a list of all the lists in the site.
Notice that the LoadQuery method returns a new list collection that you can iterate through. The new list collection has a type of IEnumerable<List> instead ofListCollection.
There is one aspect of the semantics of the LoadQuery method that you must pay attention to. In the previous example, the original lists variable does not have its property values populated after the ExecuteQuery method returns. If you want that list to be populated, you must explicitly call the Load method, specifying which properties that you want loaded.
The LoadQuery method has different semantics than the Load method. Whereas theLoad method populates the client object (or client object collection) with data from the server, the LoadQuery method populates and returns a new collection. This means that you can query the same object collection multiple times and keep separate result sets for each query. For instance, you can query for all items in a project list that are assigned to a certain person, and separately query for all items that have an estimated hours that is larger than a certain threshold, and access both result sets at the same time. It also enables you to let these collections go out of scope, and thereby become eligible for garbage collection. Collections that you load using the Load method are eligible for garbage collection only when the client context variable itself goes out of scope. Other than these differences, the LoadQuerymethod provides the same functionality as the Load method.
The following example uses the LoadQuery method to retrieve a list of all the lists in the site.
using System; using System.Collections.Generic; using Microsoft.SharePoint.Client; class Program { static void Main(string[] args) { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); Web site = clientContext.Web; ListCollection lists = site.Lists; IEnumerable<List> newListCollection = clientContext.LoadQuery( lists.Include( list => list.Title, list => list.Id, list => list.Hidden)); clientContext.ExecuteQuery(); foreach (List list in newListCollection) Console.WriteLine("Title: {0} Id: {1}", list.Title.PadRight(40), list.Id.ToString("D")); } }
There is one aspect of the semantics of the LoadQuery method that you must pay attention to. In the previous example, the original lists variable does not have its property values populated after the ExecuteQuery method returns. If you want that list to be populated, you must explicitly call the Load method, specifying which properties that you want loaded.
Increasing Performance by Nesting Include Statements in LoadQuery
When calling the LoadQuery method, you can specify multiple levels of properties to load. This allows the client object model to optimize its access to the server that runs SharePoint Foundation by reducing the number of times the client object model must call to the server that runs SharePoint Foundation to retrieve the data that you want. The following query retrieves all lists from the site, and all fields from each list. It then prints them to the console and indicates if each list or field is hidden.
using System;
using System.Collections.Generic;
using Microsoft.SharePoint.Client;
class Program
{
static void Main()
{
ClientContext clientContext =
new ClientContext("http://intranet.contoso.com");
IEnumerable<List> lists = clientContext.LoadQuery(
clientContext.Web.Lists.Include(
list => list.Title,
list => list.Hidden,
list => list.Fields.Include(
field => field.Title,
field => field.Hidden)));
clientContext.ExecuteQuery();
foreach (List list in lists)
{
Console.WriteLine("{0}List: {1}",
list.Hidden ? "Hidden " : "", list.Title);
foreach (Field field in list.Fields)
Console.WriteLine(" {0}Field: {1}",
field.Hidden ? "Hidden " : "",
field.Title);
}
}
}
This approach allows the server part of the client object model to be more efficient than if the application first loaded a list of lists, and then loaded fields for each list.
When calling the LoadQuery method, you can specify multiple levels of properties to load. This allows the client object model to optimize its access to the server that runs SharePoint Foundation by reducing the number of times the client object model must call to the server that runs SharePoint Foundation to retrieve the data that you want. The following query retrieves all lists from the site, and all fields from each list. It then prints them to the console and indicates if each list or field is hidden.
This approach allows the server part of the client object model to be more efficient than if the application first loaded a list of lists, and then loaded fields for each list.
using System; using System.Collections.Generic; using Microsoft.SharePoint.Client; class Program { static void Main() { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); IEnumerable<List> lists = clientContext.LoadQuery( clientContext.Web.Lists.Include( list => list.Title, list => list.Hidden, list => list.Fields.Include( field => field.Title, field => field.Hidden))); clientContext.ExecuteQuery(); foreach (List list in lists) { Console.WriteLine("{0}List: {1}", list.Hidden ? "Hidden " : "", list.Title); foreach (Field field in list.Fields) Console.WriteLine(" {0}Field: {1}", field.Hidden ? "Hidden " : "", field.Title); } } }
Filtering the Child Collection Returned by LoadQuery by Using LINQ
The LoadQuery method takes an object of type IQueryable<T> as its parameter, and this enables you to write LINQ queries instead of CAML to filter the results. This example returns a collection of all document libraries that are not hidden.
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.SharePoint.Client;
class Program
{
static void Main(string[] args)
{
ClientContext clientContext =
new ClientContext("http://intranet.contoso.com");
ListCollection listCollection = clientContext.Web.Lists;
IEnumerable<List> hiddenLists = clientContext.LoadQuery(
listCollection
. Where(list => !list.Hidden &&
list.BaseType == BaseType.DocumentLibrary));
clientContext.ExecuteQuery();
foreach (var list in hiddenLists)
Console.WriteLine(list.Title);
}
}
The LoadQuery method takes an object of type IQueryable<T> as its parameter, and this enables you to write LINQ queries instead of CAML to filter the results. This example returns a collection of all document libraries that are not hidden.
using System; using System.Linq; using System.Collections.Generic; using Microsoft.SharePoint.Client; class Program { static void Main(string[] args) { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); ListCollection listCollection = clientContext.Web.Lists; IEnumerable<List> hiddenLists = clientContext.LoadQuery( listCollection . Where(list => !list.Hidden && list.BaseType == BaseType.DocumentLibrary)); clientContext.ExecuteQuery(); foreach (var list in hiddenLists) Console.WriteLine(list.Title); } }
Updating Client Objects
Updating client objects by using the client object model is fairly simple. You retrieve the objects, alter properties, call the Update method for each object that you change, and then call the ExecuteQuery method. The following example modifies items in the Client API Test List, increasing the estimate for all development items by 50 percent (a common operation).
using System;
using Microsoft.SharePoint.Client;
class Program
{
static void Main(string[] args)
{
ClientContext clientContext = new ClientContext("http://intranet.contoso.com");
List list = clientContext.Web.Lists.GetByTitle("Client API Test List");
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml =
@"<View>
<Query>
<Where>
<Eq>
<FieldRef Name='Category'/>
<Value Type='Text'>Development</Value>
</Eq>
</Where>
</Query>
<RowLimit>100</RowLimit>
</View>";
ListItemCollection listItems = list.GetItems(camlQuery);
clientContext.Load(
listItems,
items => items.Include(
item => item["Category"],
item => item["Estimate"]));
clientContext.ExecuteQuery();
foreach (ListItem listItem in listItems)
{
listItem["Estimate"] = (double)listItem["Estimate"] * 1.5;
listItem.Update();
}
clientContext.ExecuteQuery();
}
}
Updating client objects by using the client object model is fairly simple. You retrieve the objects, alter properties, call the Update method for each object that you change, and then call the ExecuteQuery method. The following example modifies items in the Client API Test List, increasing the estimate for all development items by 50 percent (a common operation).
using System; using Microsoft.SharePoint.Client; class Program { static void Main(string[] args) { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); List list = clientContext.Web.Lists.GetByTitle("Client API Test List"); CamlQuery camlQuery = new CamlQuery(); camlQuery.ViewXml = @"<View> <Query> <Where> <Eq> <FieldRef Name='Category'/> <Value Type='Text'>Development</Value> </Eq> </Where> </Query> <RowLimit>100</RowLimit> </View>"; ListItemCollection listItems = list.GetItems(camlQuery); clientContext.Load( listItems, items => items.Include( item => item["Category"], item => item["Estimate"])); clientContext.ExecuteQuery(); foreach (ListItem listItem in listItems) { listItem["Estimate"] = (double)listItem["Estimate"] * 1.5; listItem.Update(); } clientContext.ExecuteQuery(); } }
Deleting Client Objects
Deleting client objects is just as easy. However, there is one very important dynamic around deleting client objects from a client object collection. You cannot iterate through the collection, deleting objects. As soon as you delete the first object, it causes the iterator of the client object collection to malfunction. The iterator may throw an exception, or it may quietly finish but not visit all items in the collection. Instead, you must materialize the collection into a List<T> using the ToList method, and then iterate through that list, deleting the client objects.
The following example deletes the test items from our Client API Test List. It shows using the ToList method to materialize the collection before you iterate through it:
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.SharePoint.Client;
class Program
{
static void Main(string[] args)
{
ClientContext clientContext = new ClientContext("http://intranet.contoso.com");
List list = clientContext.Web.Lists.GetByTitle("Client API Test List");
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml =
@"<View>
<Query>
<Where>
<Eq>
<FieldRef Name='Category'/>
<Value Type='Text'>Test</Value>
</Eq>
</Where>
</Query>
<RowLimit>100</RowLimit>
</View>";
ListItemCollection listItems = list.GetItems(camlQuery);
clientContext.Load(
listItems,
items => items.Include(
item => item["Title"]));
clientContext.ExecuteQuery();
foreach (ListItem listItem in listItems.ToList())
listItem.DeleteObject();
clientContext.ExecuteQuery();
}
}
The following code example shows the incorrect approach.
clientContext.Load(
listItems,
items => items.Include(
item => item["Title"]));
clientContext.ExecuteQuery();
// The ToList() method call is removed in the following line.
foreach (ListItem listItem in listItems)
listItem.DeleteObject();
clientContext.ExecuteQuery();
Finally, to clean up the Client API Test List, here is an example that deletes the list and its items.
Deleting client objects is just as easy. However, there is one very important dynamic around deleting client objects from a client object collection. You cannot iterate through the collection, deleting objects. As soon as you delete the first object, it causes the iterator of the client object collection to malfunction. The iterator may throw an exception, or it may quietly finish but not visit all items in the collection. Instead, you must materialize the collection into a List<T> using the ToList method, and then iterate through that list, deleting the client objects.
The following example deletes the test items from our Client API Test List. It shows using the ToList method to materialize the collection before you iterate through it:
The following code example shows the incorrect approach.
Finally, to clean up the Client API Test List, here is an example that deletes the list and its items.
The following example deletes the test items from our Client API Test List. It shows using the ToList method to materialize the collection before you iterate through it:
using System; using System.Linq; using System.Collections.Generic; using Microsoft.SharePoint.Client; class Program { static void Main(string[] args) { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); List list = clientContext.Web.Lists.GetByTitle("Client API Test List"); CamlQuery camlQuery = new CamlQuery(); camlQuery.ViewXml = @"<View> <Query> <Where> <Eq> <FieldRef Name='Category'/> <Value Type='Text'>Test</Value> </Eq> </Where> </Query> <RowLimit>100</RowLimit> </View>"; ListItemCollection listItems = list.GetItems(camlQuery); clientContext.Load( listItems, items => items.Include( item => item["Title"])); clientContext.ExecuteQuery(); foreach (ListItem listItem in listItems.ToList()) listItem.DeleteObject(); clientContext.ExecuteQuery(); } }
clientContext.Load( listItems, items => items.Include( item => item["Title"])); clientContext.ExecuteQuery(); // The ToList() method call is removed in the following line. foreach (ListItem listItem in listItems) listItem.DeleteObject(); clientContext.ExecuteQuery();
Discovering the Schema for Fields
As promised, this section shows an easy way to discover the XML schema that you use to create the fields that you want to create in a list. First, on the SharePoint site, create a list that contains columns that are configured as you want them. Then you can then use the following example to output the XML that creates those fields.
The following example prints the field schemas for the fields that I added to the Client API Test List.
using System;
using System.Linq;
using System.Xml.Linq;
using Microsoft.SharePoint.Client;
class Program
{
static void Main(string[] args)
{
ClientContext clientContext =
new ClientContext("http://intranet.contoso.com");
List list = clientContext.Web.Lists
.GetByTitle("Client API Test List");
clientContext.Load(list);
FieldCollection fields = list.Fields;
clientContext.Load(fields);
clientContext.ExecuteQuery();
foreach (var f in fields)
{
XElement e = XElement.Parse(f.SchemaXml);
string name = (string)e.Attribute("Name");
if (name == "Category" || name == "Estimate")
{
e.Attributes("ID").Remove();
e.Attributes("SourceID").Remove();
e.Attributes("ColName").Remove();
e.Attributes("RowOrdinal").Remove();
e.Attributes("StaticName").Remove();
Console.WriteLine(e);
Console.WriteLine("===============");
}
}
}
}
When you run this after you create the list by using the example program in the section Creating and Populating a List, it produces the following output.
<Field Type="Choice" DisplayName="Category" Format="Dropdown" Name="Category">
<Default>Specification</Default>
<CHOICES>
<CHOICE>Specification</CHOICE>
<CHOICE>Development</CHOICE>
<CHOICE>Test</CHOICE>
<CHOICE>Documentation</CHOICE>
</CHOICES>
</Field>
===============
<Field Type="Number" DisplayName="Estimate" Name="Estimate" />
===============
The example removes attributes that are not required for creating the field.
As promised, this section shows an easy way to discover the XML schema that you use to create the fields that you want to create in a list. First, on the SharePoint site, create a list that contains columns that are configured as you want them. Then you can then use the following example to output the XML that creates those fields.
The following example prints the field schemas for the fields that I added to the Client API Test List.
When you run this after you create the list by using the example program in the section Creating and Populating a List, it produces the following output.
The example removes attributes that are not required for creating the field.
The following example prints the field schemas for the fields that I added to the Client API Test List.
using System; using System.Linq; using System.Xml.Linq; using Microsoft.SharePoint.Client; class Program { static void Main(string[] args) { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); List list = clientContext.Web.Lists .GetByTitle("Client API Test List"); clientContext.Load(list); FieldCollection fields = list.Fields; clientContext.Load(fields); clientContext.ExecuteQuery(); foreach (var f in fields) { XElement e = XElement.Parse(f.SchemaXml); string name = (string)e.Attribute("Name"); if (name == "Category" || name == "Estimate") { e.Attributes("ID").Remove(); e.Attributes("SourceID").Remove(); e.Attributes("ColName").Remove(); e.Attributes("RowOrdinal").Remove(); e.Attributes("StaticName").Remove(); Console.WriteLine(e); Console.WriteLine("==============="); } } } }
<Field Type="Choice" DisplayName="Category" Format="Dropdown" Name="Category"> <Default>Specification</Default> <CHOICES> <CHOICE>Specification</CHOICE> <CHOICE>Development</CHOICE> <CHOICE>Test</CHOICE> <CHOICE>Documentation</CHOICE> </CHOICES> </Field> =============== <Field Type="Number" DisplayName="Estimate" Name="Estimate" /> ===============
Accessing Large Lists
SharePoint development guidelines indicate that you should not attempt to retrieve more than 2000 items in a single query. If this is a possibility in your application, consider using the RowLimit element in your CAML queries to limit how much data that the client object model retrieves for your application. Sometimes you must access all items in a list that may contain more than 2000 items. If you must do so, then best practice is to page through the items 2000 at a time. This section presents an approach to paging using the ListItemCollectionPosition property.
using System;
using System.Linq;
using Microsoft.SharePoint.Client;
class Program
{
static void Main()
{
ClientContext clientContext =
new ClientContext("http://intranet.contoso.com");
List list = clientContext.Web.Lists
.GetByTitle("Client API Test List");
// First, add 20 items to Client API Test List so that there are
// enough records to show paging.
ListItemCreationInformation itemCreateInfo =
new ListItemCreationInformation();
for (int i = 0; i < 20; i++)
{
ListItem listItem = list.AddItem(itemCreateInfo);
listItem["Title"] = String.Format("New Item #{0}", i);
listItem["Category"] = "Development";
listItem["Estimate"] = i;
listItem.Update();
}
clientContext.ExecuteQuery();
// This example shows paging through the list ten items at a time.
// In a real-world scenario, you would want to limit a page to
// 2000 items.
ListItemCollectionPosition itemPosition = null;
while (true)
{
CamlQuery camlQuery = new CamlQuery();
camlQuery.ListItemCollectionPosition = itemPosition;
camlQuery.ViewXml =
@"<View>
<ViewFields>
<FieldRef Name='Title'/>
<FieldRef Name='Category'/>
<FieldRef Name='Estimate'/>
</ViewFields>
<RowLimit>10</RowLimit>
</View>";
ListItemCollection listItems = list.GetItems(camlQuery);
clientContext.Load(listItems);
clientContext.ExecuteQuery();
itemPosition = listItems.ListItemCollectionPosition;
foreach (ListItem listItem in listItems)
Console.WriteLine(" Item Title: {0}", listItem["Title"]);
if (itemPosition == null)
break;
Console.WriteLine(itemPosition.PagingInfo);
Console.WriteLine();
}
}
}
This example produces the following output:
Item Title: Write specs for user interface.
Item Title: Develop proof-of-concept.
Item Title: Write test plan for user interface.
Item Title: Validate SharePoint interaction.
Item Title: Develop user interface.
Item Title: New Item #0
Item Title: New Item #1
Item Title: New Item #2
Item Title: New Item #3
Item Title: New Item #4
Paged=TRUE&p_ID=10
Item Title: New Item #5
Item Title: New Item #6
Item Title: New Item #7
Item Title: New Item #8
Item Title: New Item #9
Item Title: New Item #10
Item Title: New Item #11
Item Title: New Item #12
Item Title: New Item #13
Item Title: New Item #14
Paged=TRUE&p_ID=20
Item Title: New Item #15
Item Title: New Item #16
Item Title: New Item #17
Item Title: New Item #18
Item Title: New Item #19
SharePoint development guidelines indicate that you should not attempt to retrieve more than 2000 items in a single query. If this is a possibility in your application, consider using the RowLimit element in your CAML queries to limit how much data that the client object model retrieves for your application. Sometimes you must access all items in a list that may contain more than 2000 items. If you must do so, then best practice is to page through the items 2000 at a time. This section presents an approach to paging using the ListItemCollectionPosition property.
This example produces the following output:
using System; using System.Linq; using Microsoft.SharePoint.Client; class Program { static void Main() { ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); List list = clientContext.Web.Lists .GetByTitle("Client API Test List"); // First, add 20 items to Client API Test List so that there are // enough records to show paging. ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation(); for (int i = 0; i < 20; i++) { ListItem listItem = list.AddItem(itemCreateInfo); listItem["Title"] = String.Format("New Item #{0}", i); listItem["Category"] = "Development"; listItem["Estimate"] = i; listItem.Update(); } clientContext.ExecuteQuery(); // This example shows paging through the list ten items at a time. // In a real-world scenario, you would want to limit a page to // 2000 items. ListItemCollectionPosition itemPosition = null; while (true) { CamlQuery camlQuery = new CamlQuery(); camlQuery.ListItemCollectionPosition = itemPosition; camlQuery.ViewXml = @"<View> <ViewFields> <FieldRef Name='Title'/> <FieldRef Name='Category'/> <FieldRef Name='Estimate'/> </ViewFields> <RowLimit>10</RowLimit> </View>"; ListItemCollection listItems = list.GetItems(camlQuery); clientContext.Load(listItems); clientContext.ExecuteQuery(); itemPosition = listItems.ListItemCollectionPosition; foreach (ListItem listItem in listItems) Console.WriteLine(" Item Title: {0}", listItem["Title"]); if (itemPosition == null) break; Console.WriteLine(itemPosition.PagingInfo); Console.WriteLine(); } } }
Item Title: Write specs for user interface. Item Title: Develop proof-of-concept. Item Title: Write test plan for user interface. Item Title: Validate SharePoint interaction. Item Title: Develop user interface. Item Title: New Item #0 Item Title: New Item #1 Item Title: New Item #2 Item Title: New Item #3 Item Title: New Item #4 Paged=TRUE&p_ID=10 Item Title: New Item #5 Item Title: New Item #6 Item Title: New Item #7 Item Title: New Item #8 Item Title: New Item #9 Item Title: New Item #10 Item Title: New Item #11 Item Title: New Item #12 Item Title: New Item #13 Item Title: New Item #14 Paged=TRUE&p_ID=20 Item Title: New Item #15 Item Title: New Item #16 Item Title: New Item #17 Item Title: New Item #18 Item Title: New Item #19
Asynchronous Processing
If you are building an application that must attach to SharePoint sites that may not be available, or if you must regularly invoke queries that may take a long time, you should consider using asynchronous processing. This enables your application to continue to be responsive to your user while the query executes in a separate thread. In your main thread, you can set a timer to let you know if the query is taking longer than your desired threshold, you can keep the user posted with the status of the query, and when the query finally finishes, you can display the results.
The JavaScript version of the client object model and the Silverlight version (when it modifies the user interface) use asynchronous processing. The topic Data Retrieval Overview in the SharePoint 2010 SDK contains examples of how to use asynchronous processing using JavaScript and Silverlight.
When building a traditional application that is based on the .NET Framework, such as a Windows Forms or WPF application, you may want to use asynchronous processing. The following example uses the BeginInvoke method to execute a query asynchronously. Notice that the code passes a statement lambda expression to theBeginInvoke method, which makes it convenient to create this pattern, because the statement lambda expression can refer to automatic variables in the method that contains it. You can see that the statement lambda expression has access to the clientContext variable and the newListCollection variable. Microsoft Visual C# closures make the language function as you expect.
using System;
using System.Collections.Generic;
using Microsoft.SharePoint.Client;
class Program
{
static void Main(string[] args)
{
AsynchronousAccess asynchronousAccess = new AsynchronousAccess();
asynchronousAccess.Run();
Console.WriteLine("Before exiting Main");
Console.WriteLine();
Console.WriteLine("In a real application, the application can");
Console.WriteLine("continue to be responsive to the user.");
Console.WriteLine();
Console.ReadKey();
}
}
class AsynchronousAccess
{
delegate void AsynchronousDelegate();
public void Run()
{
Console.WriteLine("About to start a query that will take a long time.");
Console.WriteLine();
ClientContext clientContext =
new ClientContext("http://intranet.contoso.com");
ListCollection lists = clientContext.Web.Lists;
IEnumerable<List> newListCollection = clientContext.LoadQuery(
lists.Include(
list => list.Title));
AsynchronousDelegate executeQueryAsynchronously =
new AsynchronousDelegate(clientContext.ExecuteQuery);
executeQueryAsynchronously.BeginInvoke(
arg =>
{
clientContext.ExecuteQuery();
Console.WriteLine("Long running query completed.");
foreach (List list in newListCollection)
Console.WriteLine("Title: {0}", list.Title);
}, null);
}
}
The example produces the following output.
About to start a query that will take a long time.
Before exiting Main
In a real application, the application can
continue to be responsive to the user.
Long running query completed.
Title: Announcements
Title: Cache Profiles
Title: Calendar
Title: Client API Test List
Title: Content and Structure Reports
Title: Content type publishing error log
Title: Converted Forms
Title: Customized Reports
Title: Eric's ToDo List
Title: Eric's Wiki
Title: Form Templates
Title: Links
If you are building an application that must attach to SharePoint sites that may not be available, or if you must regularly invoke queries that may take a long time, you should consider using asynchronous processing. This enables your application to continue to be responsive to your user while the query executes in a separate thread. In your main thread, you can set a timer to let you know if the query is taking longer than your desired threshold, you can keep the user posted with the status of the query, and when the query finally finishes, you can display the results.
The JavaScript version of the client object model and the Silverlight version (when it modifies the user interface) use asynchronous processing. The topic Data Retrieval Overview in the SharePoint 2010 SDK contains examples of how to use asynchronous processing using JavaScript and Silverlight.
When building a traditional application that is based on the .NET Framework, such as a Windows Forms or WPF application, you may want to use asynchronous processing. The following example uses the BeginInvoke method to execute a query asynchronously. Notice that the code passes a statement lambda expression to theBeginInvoke method, which makes it convenient to create this pattern, because the statement lambda expression can refer to automatic variables in the method that contains it. You can see that the statement lambda expression has access to the clientContext variable and the newListCollection variable. Microsoft Visual C# closures make the language function as you expect.
The example produces the following output.
The JavaScript version of the client object model and the Silverlight version (when it modifies the user interface) use asynchronous processing. The topic Data Retrieval Overview in the SharePoint 2010 SDK contains examples of how to use asynchronous processing using JavaScript and Silverlight.
When building a traditional application that is based on the .NET Framework, such as a Windows Forms or WPF application, you may want to use asynchronous processing. The following example uses the BeginInvoke method to execute a query asynchronously. Notice that the code passes a statement lambda expression to theBeginInvoke method, which makes it convenient to create this pattern, because the statement lambda expression can refer to automatic variables in the method that contains it. You can see that the statement lambda expression has access to the clientContext variable and the newListCollection variable. Microsoft Visual C# closures make the language function as you expect.
using System; using System.Collections.Generic; using Microsoft.SharePoint.Client; class Program { static void Main(string[] args) { AsynchronousAccess asynchronousAccess = new AsynchronousAccess(); asynchronousAccess.Run(); Console.WriteLine("Before exiting Main"); Console.WriteLine(); Console.WriteLine("In a real application, the application can"); Console.WriteLine("continue to be responsive to the user."); Console.WriteLine(); Console.ReadKey(); } } class AsynchronousAccess { delegate void AsynchronousDelegate(); public void Run() { Console.WriteLine("About to start a query that will take a long time."); Console.WriteLine(); ClientContext clientContext = new ClientContext("http://intranet.contoso.com"); ListCollection lists = clientContext.Web.Lists; IEnumerable<List> newListCollection = clientContext.LoadQuery( lists.Include( list => list.Title)); AsynchronousDelegate executeQueryAsynchronously = new AsynchronousDelegate(clientContext.ExecuteQuery); executeQueryAsynchronously.BeginInvoke( arg => { clientContext.ExecuteQuery(); Console.WriteLine("Long running query completed."); foreach (List list in newListCollection) Console.WriteLine("Title: {0}", list.Title); }, null); } }
About to start a query that will take a long time. Before exiting Main In a real application, the application can continue to be responsive to the user. Long running query completed. Title: Announcements Title: Cache Profiles Title: Calendar Title: Client API Test List Title: Content and Structure Reports Title: Content type publishing error log Title: Converted Forms Title: Customized Reports Title: Eric's ToDo List Title: Eric's Wiki Title: Form Templates Title: Links
SharePoint 2010 - Complete details about Client Object Model
This is the introduction to the Client Object model introduced in the SharePoint 2010. This is going to be a huge help and useful part in SharePoint 2010 for developers and makes lot of customization to the existing SharePoint system.
In eariler versions, I mean till SharePoint 2007 the code runs using the SharePoint object model to run against the server which is running SharePoint. Other than the SharePoint server object model, other way is, simply reference the web service and use that to get and manipulate data. Then what is the need of SharePoint 2010 Client object model[Cleint OM] concept?
Now, I believe you have understood the Client OM concept. Now, we will discuss a little bit about technical implementation.
SharePoint 2010 provides the client support files to refer the SharePoint objects and communicate with the SharePoint server. Below are the details.
What we need to do is, add the relted file to the project references if it is Managed client or Silverlight and start using the SharePoint objects in the code. If it is ECMAScript then we just need to declare the line ExecuteOrDelayUntilScriptLoaded(Initialize, "sp.js"); on the top of js file to use the SP object.
**Initialize is some javascript function.**
My next posts will be the examples of each client OM implementation and how to get, manipulate data for better understanding.
In eariler versions, I mean till SharePoint 2007 the code runs using the SharePoint object model to run against the server which is running SharePoint. Other than the SharePoint server object model, other way is, simply reference the web service and use that to get and manipulate data. Then what is the need of SharePoint 2010 Client object model[Cleint OM] concept?
What is Client Object Model?
Client Object Model is introduced in SharePoint 2010 which helps to developers to make things easier to develop the client side applications for SharePoint 2010. Client Object Model can run on the client machines (Where SharePoint is not installed) and communicate with the SharePoint server remotely. This is the great advantage for the SharePoint devs as they don't have to install SharePoint for development any more.
What are the different Client OM supporting in the SharePoint 2010 API? [Client API]
- .NET Managed Client - Implemented in .NET CLR. I mean we use this in Web, Windows and Console applications.
- Silverlight Client - You can use the SharePoint objects in Silver light coding. Wow, this is going to be a huge advantage to the Silverlight applications which can be integrated into SharePoint. Before we don't have access to SharePoint objects inside Silverlight context.
- ECMAScript Client - Through javascript too, we can get context and do manipulations to SharePoint objects. Do you think it's possible? Yes, its a brilliant way of thinking from Microsoft SharePoint team and this will help in great scenarios. Will explain later in this article.
Why Client Object Model comes into the picture? Are there any specialties of them?
The main started point to think by SharePoint team are as follows.- Is it really necessary to have SharePoint installed on server for SharePoint development? - Yes, in SharePoint 2007 you have to install SharePoint on the server to write code and test it.
- What is the advantage of writing more web services to serve what the clients are looking for? - This is completely not a feasible solution to give or expose web services for each and every single requirement to get and manipulate data. It has plenty of limitations and if Microsoft exposes 500 web services and you didn't find what you really need and they are just waste. Instead write whatever you want and use them.
- The great thinking and beautiful solution to the people who don't allow server side coding in the SharePoint sites is ECMAscript client OM. You can create a simple javascript file and deploy into the server to get what you needed. As we know, most of the clients don't allow server side coding but they want something to be developed. In SharePoint 2007 it's very difficult to get this job done. But now in SP 2010 very easy.
SharePoint object model syntax:
Server side syntax | Client side syntax |
---|---|
SPContext | ClientContext |
SPSite | Site |
SPWeb | Web |
SPList | List |
SharePoint 2010 provides the client support files to refer the SharePoint objects and communicate with the SharePoint server. Below are the details.
ForManaged Client | DLL's needed : Microsoft.SharePoint.Client.dll, Microsoft.SharePoint.Client.Runtime.dll. Find these files in the 14/ISAPI folder. Usually, the location would be at "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI". |
Silverlight | Microsoft.SharePoint.Client.Silverlight.dll and Microsoft.SharePoint.Client.Silverlight.Runtime.dll. They find at "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ClientBin". |
ECMAScript | SP.js file - The file fund at "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS". |
What we need to do is, add the relted file to the project references if it is Managed client or Silverlight and start using the SharePoint objects in the code. If it is ECMAScript then we just need to declare the line ExecuteOrDelayUntilScriptLoaded(Initialize, "sp.js"); on the top of js file to use the SP object.
**Initialize is some javascript function.**
My next posts will be the examples of each client OM implementation and how to get, manipulate data for better understanding.
Working With SharePoint Data (8)
The purpose of this section is how to use sharepoint foundation web application from client object model.
Querying from Client-side Code : We have four ways to query to sharepoint foundation server
1. Querying from the clint object model.
2. querying from REST web service that implement ADO.Net data service framework.
3. Querying from inbuilt web services such as list web service, webs web service etc.
4. Querying by using owssver.dll assembly
Querying from client object model:- 2 ways to query with client object model.
1. Implement CAML Query with the CAML Query class
2. Query any sharepoint foundation object that implement I<enumerable> with Linq based query.
Using the ADO.NET Data Services Framework
If your client application does not use new client object model and you only need to query on the list data. you can always use ado.net service framework to query on content database by using ADO.net data service framework.
You should be aware of the following important differences between the ECMAScript (JavaScript, JScript) and managed client object models.
Avoid Using SharePoint Data-Providing Web Services
Avoid Making Direct Calls to owssvr.dll
Using the SharePoint Foundation Client APIs
SharePoint 2010 Client Object Model – The new client-side object model provides remote access to the functionality of the SharePoint Foundation server-side object model. In previous releases of SharePoint Foundation, SOAP web services provided access to only a fraction of the server-side object model, but in SharePoint Foundation 2010, the client object model fills many of the gaps.
ASP.NET Web Services – The legacy web services provide remote access to a SharePoint Foundation deployment through SOAP web services.
SharePoint Foundation REST Interface – The new SharePoint Foundation REST interface exposes lists and libraries as a relational data service, and serves as a standards-based interface for interoperability with other platforms.
WCF Services in SharePoint Foundation 2010 – If the combination of the other client APIs is not sufficient, extend SharePoint Foundation with your own custom web service. By default SharePoint Foundation 2010 supports creating not only custom ASP.NET web services, as in previous releases, but also custom WCF web services.
Walkthrough: Creating and Implementing a Custom WCF Service in SharePoint Foundation – This walkthrough shows how to create a WCF service that uses the server-side object model, and a Windows Forms Application that implements the service and that uses the new client-side object model and REST interface.
SharePoint 2010 Client Object Model
This section of the Microsoft SharePoint 2010 Software Development Kit (SDK) introduces three new client APIs that allow you to interact with SharePoint sites from script that executes in the browser, from code (no earlier than Microsoft .NET Framework 3.5) that executes in a .NET mana
ged application, or from code that executes in a Microsoft Silverlight 2.0 application. The new ECMAScript (JavaScript, JScript), .NET managed, and Silverlight client object models each provide a subset of the server object model that is defined in Microsoft.SharePoint.dll,
SharePoint 2010 Client Object Model Hierarchy and Identity
Microsoft SharePoint Foundation 2010 has three object models for working on the client-side. These are the managed .NET object model, the managed Silverlight object model, and the unmanaged ECMAScript (JavaScript, JScript) object model.You should be aware of the following important differences between the ECMAScript (JavaScript, JScript) and managed client object models.
- The method signature may be different, as with the ClientContext() constructor (JavaScript:ClientContext(serverRelativeUrl)). In JavaScript this constructor takes a server-relative URL, but the managed version of this constructor takes either a full URL or a Uri.
- The two object models use different data value types. The JavaScript object model does not have equivalents for all the data value types in the .NET Framework managed object model. JavaScript regards StringCollection as string[]. On the other hand, JavaScript has some values that the .NET Framework does not have, such as NaN, or negative and positive infinity.
- The JavaScript object model allows Forms authentication, but you cannot specify the authentication mechanism to connect to the server. For information about the managed client object models and Forms authentication, see Authentication in the Managed Client Object Models.
- When you are creating an item and adding it to an existing collection, further updates cannot be performed with that collection while the query is outstanding. This issue pertains to adding an item to a collection; otherwise, multiple clients can simultaneously read and write to existing items within a collection.
- As part of general security, you cannot use the JavaScript object model on a page to work with Microsoft SharePoint Foundation 2010 data unless the page contains a form digest control, for example, <SharePoint:FormDigest runat="server"/>.
- You generally cannot share variables across scopes, so for this reason you cannot use common coding patterns for try/catch/finally statements.
- A RoleDefinitionBindingCollection object used in creating role assignments does not have object identity. Therefore, if you create a new RoleDefinitionBindingCollection object and then try to use it after creating a role assignment, an error is returned.
- Some case-insensitive comparisons do not work the same way on the client as they do on the server. Some server-side comparisons use the Web site locale to do a comparison, but the client can only use invariant culture to avoid frequent round trips. SharePoint Foundation 2010 does not support case-insensitive comparisons if the server is using a Web site locale.
- Due to the limitations of an asynchronous postback, you may find that inline script is not called when the page is in certain modes, for example, when a Wiki page is in edit mode. In this case, use a ScriptManager control and its RegisterStartupScript() method to register a startup script block for executing your code, instead of using inline script.