Chapter 7. Client-side technologies

A powerful feature of Microsoft SharePoint 2013 is the rich set of libraries and tools it offers to support development of client-side solutions. Before SharePoint 2010, the only out-of-the-box method to communicate between SharePoint and a consumer application was to use WebDAV or SharePoint ASMX web services. Both of these communication techniques were restrictive, however, and not terribly easy to use. Moreover, as of SharePoint 2013, most of the ASMX web services are deprecated and you shouldn’t use them anymore. With the advent of Web 2.0 and the emerging need for a dynamic web UI, the urge to go beyond that old-style paradigm has become a necessity. In this chapter, you will see how to take advantage of the client-side technologies offered by SharePoint 2013 (as well as client-side techniques in general) to implement Web 2.0 solutions that consume SharePoint 2013 data.

Architectural overview

First of all, let’s consider an architectural overview of the available technologies. Figure 7-1 shows a schema that illustrates the new data access model architecture of SharePoint 2013, which will be familiar from Chapter 6

A diagram illustrating the relationships among all the available options in the SharePoint 2013 data access model architecture. On the client-side is the Client Object Model, which targets .NET clients, JavaScript clients, and Silverlight applications. Also on the client side are REST/OData, the REST API, and mobile support.

Figure 7-1. The SharePoint 2013 data access model architecture and the role of the Client Object Model.

From a client-side viewpoint, when you need to access SharePoint data in a strongly typed manner, you can use the REST (Representational State Transfer) API, making use of the so-called Open Data Protocol (also known as OData).

More Info

To learn more about the Open Data Protocol, consult its official website at http://www.odata.org.

Similarly, when you simply need to access data through weakly typed entities, you can use the Client Object Model or the new _api endpoint introduced with SharePoint 2013, which is just a new endpoint for consuming the _vti_bin/Client.svc REST service. For further information about the new _api endpoint, please read Chapter 9 Furthermore, in case you want to develop a Windows Phone app consuming SharePoint 2013, you can use the new SDK (software development kit) project templates and libraries available for this purpose in the latest Windows Phone SDK.

More Info

You can download the Windows Phone SDK from the Windows Phone Developer Center site at http://create.msdn.com.

Whether you prefer a strongly typed or weakly typed approach, behind the scenes you’ll find the same data foundation elements that already support the Server Object Model and LINQ to SharePoint.

Client Object Model

The Client Object Model is a set of libraries and classes with which you can consume SharePoint data through a specific object model that is a subset of the SharePoint Server Object Model.

Note

You can download the Client Object Model as a redistributable package that targets either x86 or x64 platforms. You’ll find both versions at http://www.microsoft.com/en-us/download/details.aspx?id=35585.

Figure 7-2 shows the overall architecture of the Client Object Model.

A diagram illustrating the way a client interacts with a SharePoint 2013 server. Using the Client Object Model, the client sends XML requests to the Client.svc service endpoint and retrieves JSON responses.

Figure 7-2. The architecture of the Client Object Model of SharePoint 2013.

The key advantage of Client Object Model is that it supports multiple platforms. In fact, you can use it in any solution that can run JavaScript code, via the JavaScript Client Object Model (JSOM), or in any .NET-managed application using the Client Side Object Model—even in a Silverlight solution. Behind the scenes, all these platforms consume a WCF (Windows Communication Foundation) service named Client.svc, which is published under the /_vti_bin/ folder of the current site. The service accepts REST requests as well as XML requests, and responds with JavaScript Object Notation (JSON) responses or XML Atom responses. In the following sections, you will see these different flavors of the Client Object Model.

.NET Client-Side Object Model

The .NET Client-Side Object Model (CSOM) is based on a set of .NET-managed assemblies, which reside in and can be referenced from the SharePoint15_RootISAPI folder. The most basic of these assemblies are Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll, which any 32-bit or 64-bit .NET 3.5 (or higher) project can reference. SharePoint 2013 also offers new assemblies for consuming such SharePoint Server 2013 features as Enterprise Content Management (ECM), taxonomy, user profiles, advanced search, analytics, Business Connectivity Services (BCS), and others.

After you reference at least the two main assemblies (Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll), you need to create an instance of the ClientContext class, defined in the Microsoft.SharePoint.Client namespace. This class represents the client context in which you are acting. It is also the proxy to the SharePoint server that you are targeting. You can think of the ClientContext class as the client-side version of the SPContext class. It has a couple of constructors based on the URL of the target site, provided as a String or System.Uri type. As soon as you have a valid reference to the ClientContext object, you can browse its Site and Web properties, which are references to the site collection and the site that you are targeting. Querying the contents of a list of contacts shows a code excerpt that queries the contents of a list of contacts in the current website.

Note

To provision these content types and lists, refer to the code samples in Chapter 3

Each time you want to access an object, you first need to add a request for that object by invoking the Load<T> method of the ClientContext instance. You can load as many objects as you like. Many of the client-side objects have a type name that is the same as that of the Server Object Model counterpart, except that on the client side, the SP prefix is missing. For example, SPWeb and SPSite on the server side become Web and Site on the client side. Once you are ready to effectively query SharePoint, you must invoke the ExecuteQuery method of the ClientContext instance. There is also an asynchronous version of this method, called ExecuteQueryAsync, for invoking the service asynchronously. Notice Querying the contents of a list of contacts uses an instance of the CamlQuery class to query the items contained in the target list; specifically, it passes an instance of the CamlQuery class to the GetItems method of the List instance variable representing the list on the client.

Although the Client Object Model provides you with a subset of the classes and methods from the Server Object Model, that subset comprises a rich set of types that is too wide to be covered completely here. Instead, the chapter will focus on more practical matters and later provide some concrete examples taken from everyday life.

Note

If you would like to browse the entire set of types and members available in the Client Object Model, go to the “Microsoft.SharePoint.Client namespace” MSDN page, at http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.client.aspx.

Authenticating

One important thing to know when using any class or method is how to authenticate against a SharePoint server. By default, the CSOM uses Windows integrated authentication. Occasionally, however, you may have to work with forms-based authentication or a custom authentication mechanism. The ClientContext class, through its ClientRuntimeContext base class, provides an AuthenticationMode property and a FormsAuthenticationLoginInfo property, which are useful to configure a set of forms-based authentication credentials. The following code example shows how you should change the startup code of Querying the contents of a list of contacts:

ClientContext ctx = new ClientContext("http://devbook.sp2013.local/");
ctx.AuthenticationMode = ClientAuthenticationMode.FormsAuthentication;
FormsAuthenticationLoginInfo loginInfo = new FormsAuthenticationLoginInfo {
    LoginName = "UserLoginName",
    Password = "HereYourPassword",
};
ctx.FormsAuthenticationLoginInfo = loginInfo;

Note

The Client Object Model behavior could change if you use it within a public website with an anonymous user session. In fact, some methods (for example, List.GetItems) by default cannot be called by an anonymous user. Of course, you can change default permissions to enable anonymous users to call such methods.

Data retrieval and projection

To improve performance and reduce network traffic, the data retrieval engine of the Client Object Model by default does not retrieve all of the properties of the items you load. For example, when you query the items of a list, as in Querying the contents of a list of contacts, and you try to access the DisplayName property of an item, a PropertyOrFieldNotInitializedException is thrown, with the following description:

Unhandled Exception: Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException: The property or field 'DisplayName' has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.

Table 7-1 presents the list of properties that are not automatically retrieved unless you explicitly request them for the main client-side types.

Note

For further details about data retrieval policies, see the “Data Retrieval Overview” MSDN page, at http://msdn.microsoft.com/en-us/library/ee539350.aspx.

Table 7-1. Properties that are not automatically retrieved through the Client Object Model

Type

Properties not available by default

Folder

ContentTypeOrder, UniqueContentTypeOrder

List

BrowserFileHandling, DataSource, EffectiveBasePermissions, HasUniqueRoleAssignments, IsSiteAssetsLibrary, OnQuickLaunch, RoleAssignments, SchemaXml, ValidationFormula, ValidationMessage

ListItem

DisplayName, EffectiveBasePermissions, HasUniqueRoleAssignments, RoleAssignments

SecurableObject

HasUniqueRoleAssignments, RoleAssignments

Site

Usage

Web

EffectiveBasePermissions, HasUniqueRoleAssignments, RoleAssignments

Querying the contents of a list of contacts, including some extra properties shows how to instruct the ClientContext to retrieve the DisplayName and the RoleAssignments properties for each ListItem instance.

The code sample uses the ClientContext.Load<T> method, which accepts a parameter array of expressions of type Expression<Func<T, Object>>. Here is the method signature:

public void Load<T>(
    T clientObject,
    params Expression<Func<T, Object>>[] retrievals)
where T : ClientObject

The expressions define the properties to retrieve from the server. In Querying the contents of a list of contacts, including some extra properties, they are defined using lambda expressions. However, the code excerpt of Querying the contents of a list of contacts, including some extra properties is a little bit stressing for the server. In fact, each item in the list of contacts queries the server for its own extra properties. It would be better to instruct the ClientContext to retrieve all the properties at one time. Luckily, the Client Object Model also provides an extension method called IncludeWithDefaultProperties. Defined in type ClientObjectQueryableExtension, the IncludeWithDefaultProperties method instructs the ClientContext object about the properties to retrieve by default when querying a target list of objects. Querying the contents of a list of contacts, including some extra properties, into the default list of properties shows a revised version of the code of Querying the contents of a list of contacts, including some extra properties.

If you would like to selectively define the fields to retrieve from the target list, you can use the Collaborative Application Markup Language (CAML) query definition to specify the fields to retrieve, setting the ViewFields property. Querying the contents of a list of contacts and projecting fields in the output shows the syntax.

Of course, if you try to access a field that is not explicitly declared in the query, you will get a PropertyOrFieldNotInitializedException, as with the previous examples.

Another technique to project a subset of fields for a query is to use the Include extension method, still defined in type ClientObjectQueryableExtension. Querying the contents of a list of contacts and projecting fields in the output without using CAML presents the syntax, which produces a result equivalent to Querying the contents of a list of contacts and projecting fields in the output, but without involving CAML.

The signature of the Include method accepts an array of Expression<Func<TSource, object>> arguments, which define a set of inclusion rules. In Querying the contents of a list of contacts and projecting fields in the output without using CAML, these expressions are defined using some lambda expressions.

As with custom projection rules, you can also use CAML to define custom filters (for instance, data partitioning) on data to retrieve. For example, you could select only the contacts with a value of Italy in the DevLeapCountry field by using a <Where /> CAML clause. However, one great feature of the CSOM is the support for LINQ queries. In fact, when you work with the CSOM, you can provide LINQ queries to a LoadQuery<T>-specific method, which will convert these queries into requests for the SharePoint server.

Important

Be aware that when you define LINQ queries with the CSOM, you are using LINQ to Objects, not the custom LINQ to SharePoint query provider discussed in Chapter 6. This implies that you do not have all the infrastructural services provided by the LINQ to SharePoint query provider.

Querying the contents of a list of contacts using a LINQ query presents a code excerpt that uses LINQ to Objects and the Client Object Model to query for the Italian contacts.

The key point of Querying the contents of a list of contacts using a LINQ query is the invocation of method LoadQuery<T>, which provides the following pair of overloads:

public IEnumerable<T> LoadQuery<T>(ClientObjectCollection<T> clientObjects)
    where T : ClientObject;
public IEnumerable<T> LoadQuery<T>(IQueryable<T> clientObjects)
    where T : ClientObject;

Similar to the Load<T> method, the LoadQuery<T> method works only with a result inheriting from ClientObject. As a consequence of this behavior, you cannot use the LoadQuery<T> method to retrieve custom anonymous types, projecting only a subset of the available fields of an item. The main difference between Load<T> and LoadQuery<T> is that the former loads data into the client objects retrieved from the SharePoint server; the latter returns an object of type IEnumerable<T> that represents an independent collection of items. This behavior implies that the object instances allocated by Load<T> will be released by the garbage collector when the ClientContext object goes out of scope, while object instances returned by LoadQuery<T> can be collected independently from the ClientContext.

ClientObject vs. ClientValueObject

The ClientObject type is the base abstract class defined in the .NET Client Object Model to describe any object retrieved on a remote client. The Client Object Model also provides a base abstract ClientValueObject class, which represents a client-side version of a server-side property value. For example, a ListItem type is a class inherited from ClientObject, while the ContentTypeId property of a ListItem is a class inherited from ClientValueObject. For the sake of thoroughness, a property like the Title property of a List instance is a scalar value and behaves like any classic .NET type.

The main difference between an object inherited from the ClientObject class and one inherited from ClientValueObject lies in their behavior when using them within a query or a method call. In fact, you cannot use a ClientValueObject-inherited object as the argument of a method or inside a query, unless you have not retrieved it from the server. However, you can reference a ClientObject-inherited object in another method call or query definition, even if you did not already retrieve it from the server, because it will be correctly resolved by the CSOM.

Using a ClientObject-inherited object in a direct method call illustrates a query based on objects inherited from ClientObject, such as the Web and the List properties.

The code sample works correctly because the ClientObject-inherited properties will be handled by the CSOM. However, if you try to access some of the properties of the Web instance of the current ClientContext object, you will get an exception. For example, the following instruction will fail unless you explicitly do not load the Title property of the current website:

Console.WriteLine(ctx.Web.Title);

Incorrect use of a ClientValueObject-inherited object before loading its value presents a code excerpt that illustrates the incorrect use of a ClientValueObject-inherited object.

Here, the code fails, throwing a PropertyOrFieldNotInitializedException, because you need to explicitly load the ClientValueObject-inherited object representing the Web instance before using it. Using a ClientValueObject-inherited object properly by loading its value before referencing it shows the working code example.

Using a ClientValueObject-inherited object properly by loading its value before referencing it correctly loads the Title property of the current Web object before using it in the subsequent GetByTitle method call.

You can also use the method IsPropertyAvailable, inherited from ClientObject, to test the presence of a specific scalar property in a current ClientObject instance.

Important

If the property you are looking for exists in the item schema, but it is missing on the client side, you can use the Retrieve method to explicitly retrieve all the scalar properties of a ClientObject instance, or just a set of specific scalar properties. The Retrieve method is documented on MSDN as “reserved for internal use only,” however, so you use it at your own risk.

Silverlight Client Object Model

The Silverlight Client Object Model behaves almost the same as the .NET CSOM. You can find it in the SharePoint15_RootTEMPLATELAYOUTSClientBin folder, and you can use it in any Silverlight 3.0 (or higher) solution by referencing the two main assemblies, Microsoft.SharePoint.Client.Silverlight.dll and Microsoft.SharePoint.Client.Silverlight.Runtime.dll. Like the CSOM, the Silverlight Client Object Model also supports development for such SharePoint Server 2013 features as ECM, user profiles, taxonomy, and so on.

Note

If you would like to learn more about developing with Microsoft Silverlight, read Microsoft Silverlight 4 Step by Step, by Laurence Moroney (Microsoft Press, 2010).

The Silverlight Client Object Model is useful whenever you need to develop a Silverlight solution that needs to interact with data stored in a SharePoint site. For example, you can use it to build a custom data entry UI or a custom visualization of data that’s ready for hosting with the Silverlight Web Part.

Imagine that you want to show the contacts contained in the sample list from the previous example by using a custom Silverlight control. First, you create a Silverlight application, and then you make a reference to the Silverlight Client Object Model assemblies. Now, assume that you want to render the contacts with a ListBox control, using a custom ItemTemplate for rendering. The XAML code of the Main control of the sample Silverlight application shows the XAML (Extensible Application Markup Language) code of the Main control of the sample application.

In The XAML code of the Main control of the sample Silverlight application, the XAML code by itself is not particularly exciting; it just defines a Grid control, with a ListBox control inside and a DataTemplate control for rendering each item of the contacts list. The code behind the user control is more interesting, because it makes use of the Silverlight Client Object Model. The code behind the XAML user control of the sample Silverlight application gives you a look at the code behind the user control.

The syntax is almost the same as that used with the CSOM. However, a small but significant difference is the way the code retrieves a reference to the ClientContext object. Because the Silverlight control must be hosted within a website, you could construct the Silverlight version of ClientContext by using the default constructor, which requires the target website as an argument of type System.Uri. Alternatively, you could take advantage of a shortcut to the current website context by using the ClientContext.Current static entry point. This is a constructive shortcut, because many times the Silverlight control will be hosted exactly in the same website that it will target. Furthermore, consider that the ClientContext.Current property internally uses a custom Silverlight init parameter with the name MS.SP.url and the value of the current context URL, provided to the Silverlight environment at startup. If you host your control using the Silverlight Web Part, then this init parameter, together with a few others, will be automatically provided to the control. However, if you directly insert the control inside a page, without using a Silverlight Web Part, then the ClientContext.Current property will be null unless you do not provide the MS.SP.url init parameter by yourself.

Note

The init parameters automatically provided by the Silverlight Web Part are MS.SP.url, MS.SP.formDigest, MS.SP.formDigestTimeoutSeconds, MS.SP.requestToken, and MS.SP.viaUrl.

Another fundamental difference between this sample and the one based on the CSOM is the use of an asynchronous programming model. This is not a kind of virtuosity, but a real need, because in Silverlight you have to work within the confines of the asynchronous programming pattern. In fact, while working with Silverlight, if you try to execute some blocking code from the main UI thread, you will get an exception of type InvalidOperationException with the following message:

The method or property that is called may block the UI thread and is not allowed. Please use
a background thread to invoke the method or property, for example, using System.Threading.
ThreadPool.QueueUserWorkItem method to invoke the method or property.

The Silverlight Client Object Model also provides a synchronous pattern based on the ExecuteQuery method used in the CSOM. You can call this method only from threads that do not modify the UI, however.

The code behind the XAML user control of the sample Silverlight application shows that the sample directly binds the ListItemCollection retrieved from the server to the ListBox control. However, as you probably know, every ListItem object of SharePoint has its fields stored in a named collection, and the XAML binding syntax does not support named collections. Nevertheless, the code in The XAML code of the Main control of the sample Silverlight application binds the fields using markup. This is possible because the XAML references a custom converter registered as a resource of the user control. In XAML (for instance, Silverlight and Windows Presentation Foundation [WPF]), a converter is a type that converts one input bound to a control into another output, rendering the output of the conversion. In the XAML sample code in The XAML code of the Main control of the sample Silverlight application, the converter converts the name of a field of a ListItem object into the corresponding field value. A custom converter, converting from a named field to its value displays the source code of the custom converter. If you do not like to use a custom converter, you can wrap ListItem instances with a custom type of your own.

In a real solution, the converter could be more complete and accurate, but for the sake of simplicity, A custom converter, converting from a named field to its value uses a concise implementation.

Aside from binding rules and asynchronous programming tasks, the Silverlight Client Object Model has the same potential, capabilities, and recommended procedures as the Client Object Model. Consider, however, that Silverlight is a discontinued technology. Thus, you should not invest too much time in developing new solutions based on it.

The JSOM

The third client object model offered by SharePoint targets the ECMAScript world. Often called the JavaScript Object Model (JSOM), it is a set of .js files built for ECMAScript-enabled (JavaScript, JScript) platforms. The main .js files that are available are

  • SP.js

  • SP.Core.js

  • SP.Ribbon.js

  • SP.Runtime.js

These files are deployed in the SharePoint15_RootTEMPLATELAYOUTS directory and are automatically downloaded to the client (web browser) when a user browses to a SharePoint page. In fact, the default master pages of SharePoint define a ScriptManager control, which automatically includes references to these .js files. You could also reference them by yourself, however, within a custom ASPX page. Every file is also available with a debug-enabled version—these filenames end with .debug.js instead of .js. For example, the SP.js file is also available in a debug version, named SP.debug.js. The browsers supported by the scripts include Microsoft Internet Explorer 7 and higher, Firefox 3.5 and higher, and Safari 4.0 and higher.

Important

For security reasons, you cannot use the JSOM in a page unless that page contains a form digest for security validation. SharePoint native pages, of course, include the SharePoint:FormDigest control. If you use the Client Object Model within a custom ASPX page, you will need to include the FormDigest control by yourself.

In everyday life, you will probably use the JSOM in a custom SharePoint page, in a custom Web Part, or in a SharePoint app that consumes a remote SharePoint web site. For a SharePoint page or a Web Part, you will need to create a new empty SharePoint project and add an item (for example, an Application Page item) to it. In order to reference the scripts, you can use the SharePoint:ScriptLink control, which accepts a set of arguments, including the following:

  • LoadAfterUI. Loads the script after the code of the UI

  • Localizable. Indicates if the current page can be localized

  • Name. Defines the relative path of the .js file to include in the page

Then you need to define a script block that uses the object model. Although the CSOM and the Silverlight Client Object Model share almost the same syntax, the JSOM does not. The data types used do not completely correspond on both platforms, and the members’ names differ. For example, to access the Title property of an item from the JSOM, you need to invoke the get_title() method. In addition, some arguments are case sensitive, and there are other differences. A SharePoint application page using the JSOM shows an example of an application page that uses the JSOM to retrieve a List instance and show its Title property.

The core of A SharePoint application page using the JSOM is in the method retrieveContacts, where the syntax is not so different from the other versions of the Client Object Model. You can get a reference to an SP.ClientContext instance either by using the get_current() method from A SharePoint application page using the JSOM or by using a constructor that accepts the server-relative URL of the target site. The latter syntax is useful when you need to work with data from a target site that differs from the site at your location (for example, when your code is in a remote SharePoint app). The only fundamental difference is syntactical and involves using the get_ and set_ prefixes for every property accessor, as well as using the asynchronous pattern when executing the query against the SharePoint server. For a more interesting and powerful example of this, consider A SharePoint application page using jQuery together with the JSOM, which combines jQuery with the JSOM.

A SharePoint application page using jQuery together with the JSOM uses jQuery version 1.8.3, which is the most current version at the time of this writing. It also uses a custom jQuery UI theme (named Redmond). For the sake of simplicity, the sample project loads the .js file of the jQuery world, the CSS (Cascading Style Sheets) code, and images of the UI theme from publicly available content delivery networks (CDNs). Additionally, the sample page of A SharePoint application page using jQuery together with the JSOM loads the well-known list of contacts and renders them using a custom selectable order list. The core methods are InitData, to configure and start downloading data, and dataBindList, which renders the items retrieved. The first thing you should notice is the invocation of a method to execute the InitData function as soon as the page loads; the method uses this syntax:

_spBodyOnLoadFunctionNames.push("InitData");

This method is provided by the JavaScript infrastructure of SharePoint and can be implemented in any page. The InitData function prepares and loads the queries, executing them asynchronously to keep the UI fluent, even when downloading data. The syntax used here is not substantially different from before. As soon as data is available, the dataBindList method does the real job: using jQuery to enumerate the list items and bind them to dynamic HTML content. Figure 7-3 depicts the output of the application page implemented with jQuery and the JSOM.

A screen shot displaying the list of sample contacts. One contact was selected and highlighted using the jQuery UI style with the Redmond theme.

Figure 7-3. A sample SharePoint page that uses jQuery and the JSOM.

More generally, you can consider using the JSOM whenever you need to dynamically load or even change SharePoint data from a JavaScript-enabled environment; you can use it in conjunction with jQuery or while developing custom ribbons. You will learn about this in Chapter 12 Another scenario in which you will surely use the JSOM is when developing custom SharePoint apps, as you will discover in Part III

Client Object Model examples

This section provides examples of common operations that use the CSOM within a .NET-managed client or a Silverlight control. The operations fall into two basic categories:

  • Working with lists and items

  • Managing document libraries and files

More Info

For further examples about these topics, you can also have a look at the “Apps for Office and SharePoint Samples” page on MSDN, at http://code.msdn.microsoft.com/officeapps.

Creating a new list

Creating new contents using the CSOM involves using some types specifically provided for the purpose. In fact, from the client viewpoint, the creation of a new List—or new ListItem, or whatever else—implies the need to request that the server execute the necessary action. Thus, for creating a new list, there is a class named ListCreationInformation, which describes the request to create a new list instance. The code excerpt in Creating a new List instance using the CSOM uses this type to create a new list of contacts.

Creating a new List instance using the CSOM demonstrates how the ListCreationInformation instance defines the main properties of the list to be created, such as Title, Description, and QuickLaunchOption. The object also defines the TemplateType property, which defines the base model to use for creating the list instance. If you want to create a new list instance based on a custom list definition, you can use the property ListCreationInformation.TemplateFeatureId to reference the GUID (globally unique identifier) of the feature provisioning the list definition.

More Info

For further details about data provisioning, refer to Chapter 3.

If you try to create a list that already exists with the Title provided by your code, you will get an exception of type Microsoft.SharePoint.Client.ServerException, with the following error message:

Unhandled Exception: Microsoft.SharePoint.Client.ServerException: A list, survey, discussion
board, or document library with the specified title already exists in this Web site. Please
choose another title.

One last thing to consider is that just after ExecuteQuery method invocation, the List instance you get back from the Add method of the Lists property is a fully functional instance that you can use to add items, configure properties, and so on.

Creating and updating a list item

When you create a list instance, you need to add new items to the list. Creating a new list item using the CSOM demonstrates how to add a contact to the newly created list of contacts.

Creating a new list item using the CSOM adds the ListItem object to the List instance using a ListItemCreationInformation type, which simply defines a creation task for a new ListItem. The result of the AddItem method is a ListItem instance that can be used to configure fields of the item, and then finally allows the Update method to be invoked to confirm the values of the fields. As usual with the CSOM, however, you need to inform the server about what you want to do. Thus, you need to call the ExecuteQuery method on the ClientContext instance.

Updating a ListItem instance is similar to creating a new item. The only difference is that you need to retrieve the item from the store. You can do this by enumerating the items returned from a CamlQuery object, as shown in A SharePoint application page using jQuery together with the JSOM, or you can retrieve a specific item by ID using the GetItemById method of the List type. Updating a list item by using the CSOM presents an example of updating the item created in Creating a new list item using the CSOM.

Exception handling with lists

While working with lists and items, you occasionally may look for one that does not exist. Due to the architecture of the Client Object Model, you must query the server to determine if the desired item exists. Suppose you use a try…catch code block to trap the exception related to the missing item. In this case, the exception would be a ServerException, with the following error message:

Unhandled Exception: Microsoft.SharePoint.Client.ServerException: Item does not exist. It
may have been deleted by another user.

You could then follow a backup path to avoid issues on the client side, create the missing item from scratch, or try to retrieve another item. If you look for a list that does not exist, you’ll receive the following exception:

Unhandled Exception: Microsoft.SharePoint.Client.ServerException: List 'Contacts CSOM' does not exist at site with URL 'http://devbook.sp2013.local'.

This time, you will probably need to query the server for new data or create the missing list. Code excerpt showing how to retrieve or create a list in the event that it is missing, and then add an item to it illustrates one possible scenario.

The boldface code in Code excerpt showing how to retrieve or create a list in the event that it is missing, and then add an item to it shows the three calls to the ExecuteQuery method. In the worst situation, this code could execute all the try…catch…finally blocks, invoking the server via ExecuteQuery three times. This could lead to performance degradation and also put a great deal of stress on the server side. Luckily, the CSOM provides a class named ExceptionHandlingScope that is specifically defined to support such situations and avoid executing multiple queries against the server.

The prototype for using ExceptionHandlingScope displays the prototype of using the ExceptionHandlingScope type.

Behind the scenes, the ExceptionHandlingScope instance collects activities (internally called ClientActions) to execute on the server side for all the three situations (try, catch, and finally). The server will begin executing the code inside the StartTry block, and then in case of failure, it will execute the code in the StartCatch block. Regardless of whether exceptions occur in the StartTry block, the server will finally execute the code in the StartFinally block. However, the request sent to the server defining all the previously described code blocks is just one, as well as the response. The complete code to retrieve or create a list in the event that it is missing, and then add an item to it presents a complete example.

Deleting an existing list item

Another common scenario is deleting an item from a list. Deleting a ListItem instance illustrates how to do this.

This is very similar to the syntax used to update an item. The only difference is the invocation of the DeleteObject method.

Paging queries of list items

Already in this chapter you’ve seen many ways of querying items in a list. Real-life applications, however, can contain thousands of items. Thus, it is not realistic to query these items with a unique query batch as shown in these smaller-scale examples. For such situations, take advantage of the paging capabilities of the SharePoint querying engine. How to efficiently paginate query results using the CSOM shows a code excerpt that demonstrates how to efficiently paginate query results.

First, to paginate data, you need to instruct the CAML query about the page size by using a <RowLimit/> element. In this example, the page size is 10 items per page. Next, declare a variable of type ListItemCollectionPosition to define a paging context for the running CamlQuery object. Each time you execute the query, which invokes the GetItems method of the List instance, set the property ListItemCollectionPosition of the query in order to instruct SharePoint about the page that you want to retrieve. You can retrieve the value to provide for each page from the ListItemCollectionPosition property of the class ListItemCollection. When retrieving the last page, the ListItemCollectionPosition property will have a null value, and you will know that you’ve consumed the whole set of data.

Creating a new document library

In addition to creating a standard list, at times you will need to create a custom document library. Creating a custom document library demonstrates the code to do the job.

The only difference between Creating a custom document library and Creating a new List instance using the CSOM is the value of ListTemplateType. For a document library, you could also define a DocumentTemplateType property to specify a custom document template.

Uploading and downloading documents

Uploading files to and downloading files from a document library is simple. To upload, use code similar to that shown in Uploading a file to a document library using the CSOM.

The key point of Uploading a file to a document library using the CSOM is the creation of an instance of FileCreationInformation type. The FileCreationInformation instance accepts a relative value for the Url property of the file to upload, and then collects the file in the right folder, based on the folder where the FileCreationInformation instance will be added. To upload a file, you can use the SaveBinaryDirect static method provided by the File class.

To avoid problems while uploading files, be careful to check the maximum upload file size. If necessary, you have the option to increase the maximum upload file size.

Downloading a file from a document library using the CSOM illustrates downloading a file.

Notice that the listing retrieves a Stream object from the FileInformation object to manage the file at a low level. Additionally, the FileInformation instance can be retrieved by invoking the OpenBinaryDirect static method of the File class.

Checking documents in and out

As with downloading and uploading a file, to check a document in and out, you need to use the corresponding methods File.CheckIn and File.CheckOut. It’s a good habit to check the CheckOutType property of the current File instance to determine if the file has to be checked in or checked out. Check-in and checkout of a file in a document library using the CSOM provides an example.

Just as on the Server Object Model, the CheckIn method allows you specify the revision (minor, major, or overwrite) of the document that you want to check in.

Copying and moving files

To copy and move a file from a document library, you first need to retrieve a reference to the target File instance, as you did in the previous examples. Once you have the reference, you can invoke the MoveTo method or the CopyTo method, depending on whether you want to move the file or copy it. Copying or moving a file between document libraries demonstrates how.

Both of these methods accept some parameters beyond the destination file relative URL. The CopyTo method accepts a Boolean argument that determines if the file should overwrite any existing destination item, and the MoveTo method uses an enumeration for almost the same purpose. Note that both methods copy or move not only the binary content of the file, but also its field values (metadata).

The REST API

The last client-side API that I’ll discuss in this chapter is the REST API, a feature introduced with SharePoint 2010 that has been greatly improved in SharePoint 2013.

Note

REST (Representational State Transfer) embodies the idea of accessing data across the Internet network, referencing resources using a clear and unique syntax. For example, when you open a browser and navigate to the URL http://www.microsoft.com, you identify Microsoft’s website using its identifying URL, and a web server at Microsoft returns the content you requested. When you browse to http://www.w3.org, you use a different URL that identifies a different resource. A REST API is an API that represents commands and instructions using a similar paradigm.

As you will see in this section, you will have the opportunity to reference a resource published by a SharePoint website by using a unique URL, which is a representation of that item. For further details about REST, refer to the document that first introduced the concept of REST in 2000, which is available at http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm.

SharePoint 2013 publishes a WCF service endpoint that can provide data using a REST protocol. This service listens at the virtual URL /_vti_bin/ListData.svc of every SharePoint website and can be used by any third party willing to read and eventually change data stored in SharePoint.

If you open your browser and navigate to the URL of the REST service, you will get back an XML list of all the available contents of the target SharePoint website. Figure 7-4 shows an example of what the browser returns when you query the REST service for this book’s sample site (http://devbook.sp2013.local/_vti_bin/ListData.svc).

A screen shot of the XML output returned while invoking the URL of the ListData.svc endpoint within a web browser. The figure shows many of the XML nodes enumerating lists and libraries available in the current site.

Figure 7-4. The result of requesting the ListData.svc endpoint on this book’s sample site.

Note

To read the representation of the list’s contents as XML in Internet Explorer, you first need to turn off the “Feed reading view” feature. To do so, go to Tools | Internet Options | Content | Feeds And Web Slices | Settings, and then clear the check box adjacent to Turn On Feed Reading View.

As Figure 7-4 illustrates, the result is a collection of items, each with its own relative URL (href attribute) corresponding to the lists contained in the current site. If you try to access the REST service URL, appending one of these relative URLs to the service URL, you will gain access to the content of the corresponding list. For example, suppose you request the following URL:

http://devbook.sp2013.local/_vti_bin/ListData.svc/DevLeapContacts

By default, the browser will show you a list of items in the form of a syndication feed, because the output XML is built using the Atom Syndication format (see http://www.w3.org/2005/Atom). If you request a URL such as the following, then the REST service will return the XML representation of the contact with an ID value of 1.

http://devbook.sp2013.local/_vti_bin/ListData.svc/DevLeapContacts(1)

If you need to retrieve the value of the field CompanyName of the item with an ID value of 1, you can request the following URL:

http://devbook.sp2013.local/_vti_bin/ListData.svc/DevLeapContacts(1)/CompanyName

Still, the result of this last query will be wrapped in an XML element. However, if you are interested in retrieving only the bare value, you can append to the URL the command /$value, and the REST service will return only the text value of the CompanyName field.

http://devbook.sp2013.local/_vti_bin/ListData.svc/DevLeapContacts(1)/CompanyName/$value

In general, the URI mapping access rule is like the following:

http://siteurl/_vti_bin/ListData.svc/{EntityName}[({Identifier})]/[{Property}]/[{$command}]

This is a very useful interface for querying data by using a URL-based syntax that can be consumed by any device able to access HTTP and to read XML (which today means almost any device at all). You can use the same URL syntax to write queries to partition (filter) data, to order data, to query paged data, and so on. The following list presents the main keywords available as query string parameters:

  • $filter={predicate}. Filter the data.

  • $expand={Entity}. Include related objects.

  • $orderby={property}. Order results.

  • $skip=n. Skip the first n results (useful for paging).

  • $top=n. Retrieve the first n results (also useful for paging).

  • $metadata. Get metadata describing the published entities.

The syntax that is being used is based on an open standard called OData, as proposed by Microsoft under the Microsoft Open Specification Promise.

More Info

For further details about the Microsoft Open Specification Promise, see http://www.microsoft.com/openspecifications/en/us/programs/osp/default.aspx. To find out more about OData, see http://www.odata.org.

Querying for data with .NET and LINQ

The previous section showed you how to consume the SharePoint REST API using an HTTP client, such as the WebClient class of System.Net. However, it wouldn’t be very pleasant to manually compose all the URLs corresponding to every kind of query, and then manually parse the responses in XML (Atom) format. Fortunately, Microsoft Visual Studio and .NET provide established support for services compliant with the OData specification. In fact, if you add a service reference to the ListData.svc service within a Visual Studio 2012 .NET project, the environment will recognize the service as an OData service and will provide you with a high-level interface to access the published resources.

Every OData service can provide a set of metadata, which is available by invoking the URL $metadata, and the Add Service Reference tool can read this metadata to create a set of typed classes representing each published resource. Figure 7-5 shows the Add Service Reference dialog box while a reference to an OData-compliant service is being added. Remember that you must refresh the reference each time you change or update the schema of your data in SharePoint.

A screen shot depicting the Add Service Reference dialog box provided by Visual Studio 2012. The Address field enables you to search on a specific service, such as the ListData.svc REST service, shown here. Alternatively, you can click the Discover icon to browse available services.

Figure 7-5. The Add Service Reference dialog box, shown while adding a reference to an OData-compliant service.

After you create a service reference to an OData service, you will be able to create an instance of an object called {ServiceName}DataContext that represents the proxy to the service and inherits from System.Data.Services.Client.DataServiceContext. If you’re using a SharePoint REST service, the proxy class will have a name like {SiteTitle}DataContext, where SiteTitle represents the title of the target site, without spaces. In the book’s example, the site title is DevLeap Book Portal, so the class will have a long but clear and self-explanatory name: DevLeapBookPortalDataContext.

Through instances of this class, you will be able to access and query the list items of the site as if they were collections of typed entities. In fact, every list corresponds to a collection property of the proxy class. Every content type corresponds to an entity type. For instance, for the book’s sample site, the DevLeap Contacts list of SharePoint will correspond to a DevLeapContacts collection property of the proxy class. This collection will host typed instances of contact items. Querying contacts using the REST proxy displays an example of querying the contacts using the REST proxy.

Querying contacts using the REST proxy shows that the DataContext class provides a constructor that requires an argument of type System.Uri that corresponds to the URL of the ListData.svc service endpoint. If you need to authenticate this against the remote service, you can use the Credentials property of the DataContext class. This property accepts a type implementing System.Net.ICredential, which for example is implemented by the System.Net.CredentialCache.DefaultCredentials class, and which corresponds to the system credentials of the current application. Then you only need to query (enumerate) the content of the collections in which you are interested to access the corresponding items.

One interesting thing to know is that the autogenerated code supports LINQ queries, too. Thus, you can write a query targeting the collections of items published by the DataContext class, as shown in Querying contacts by using a LINQ query. Furthermore, the LINQ query is not a LINQ to Objects query working in memory; rather, it is a query managed by a query provider that will translate the LINQ query into a REST (OData-style) query.

More Info

For further details about LINQ, read the book Programming Microsoft LINQ in Microsoft .NET Framework 4, by Paolo Pialorsi and Marco Russo (Microsoft Press, 2010).

Notice that the DevLeapContacts property of the DataContext class is of type System.Data.Services.Client.DataServiceQuery<DevLeapContactsItem>. The DataServiceQuery<T> class implements the IQueryable<T> interface of the LINQ infrastructure and represents the proxy to the OData LINQ query provider, also known as WCF Data Services Client Library.

More Info

If you would like to go deeper into WCF Data Services, see the “WCF Data Services” page on MSDN, at http://msdn.microsoft.com/en-us/library/cc668792.aspx.

If you step into the code and add a watch on the query variable, you will see that the variable internally represents the query as a REST request, as with the following:

http://devbook.sp2013.local/_vti_bin/ListData.svc/DevLeapContacts()?$filter=ContentType
  eq 'DevLeapCustomer'&$select=ContactID,Title,CompanyName,CustomerLevelValue

If you try to copy this URL and paste it into the browser address bar, you will get back exactly the results of the query, represented in XML format.

If you like to query data of a SharePoint site while ignoring that it is a SharePoint site, then the REST way is your way, because you have a typed collection of items—even queryable with LINQ—that abstracts from the underlying repository. Of course there are some limitations with this approach. For instance, you cannot write just any kind of query, and there are some keywords and operators (join, average, First, FirstOrDefault, and so on) that by now are not supported by the WCF Data Services Client Library. If you try to invoke an unsupported query command, you will get back an exception like the following one:

Unhandled Exception: System.NotSupportedException: The method 'Join' is not supported.

Note

The full list of unsupported keywords and methods can be found on MSDN, at http://msdn.microsoft.com/library/ee622463.aspx.

An unsupported query syntax displays a code excerpt of an unsupported query syntax.

However, there are already a lot of useful commands and keywords that are supported. For example, you can do paging by using Skip and Take, and you can do ordering and more. Paging in a LINQ query demonstrates how to implement paging across a list of items.

The URL request corresponding to the query in Paging in a LINQ query is the following:

http://devbook.sp2013.local/_vti_bin/ListData.svc/ContactsCOM()?$skip=10&$top=10

You can see the $skip and $top parameters illustrated in the previous section, which apply the paging rules defined in the code of Paging in a LINQ query.

Managing data

The ability to query SharePoint data using the REST API is very interesting and by itself is probably sufficient to boost the enthusiasm level for this API. However, this is just half of the story. With the REST API, from the perspective of the OData specification, you can also manage (insert, update, or delete) data using a fully typed approach, even if you are working on the client side.

The DataContext class provides an identity management service, which allows working with retrieved entities as though they were entities of a typical object-relational mapper (O/RM), such as LINQ to SQL, LINQ to Entities, or LINQ to SharePoint.

Whenever you retrieve an entity—not a custom anonymous type based on a custom projection—you can manage its properties and inform the source SharePoint server about your changes, applying them with a batch job. Updating a previously existing item via REST shows a code excerpt that updates the property of an existing item.

As the code sample shows, immediately after updating the entity, you need to manually invoke the UpdateObject method of the DataContext class to instruct it about the change you made. This is a requirement because internally the DataContext proxy class does not automatically track changes to objects. You can change many entities at the same time, and when you have finished, you simply need to invoke the SaveChanges method of the DataContext object in order to send your changes back to the server.

If you need to add a new item to a target list, you can use the general-purpose AddObject method provided by the DataContext class. In the following snippet, you can see the signature of this method:

public void AddObject(string entitySetName, object entity);

You can also use a fully typed method called AddTo{ListName}, which is a wrapper around the AddObject untyped method, and is automatically generated by the tools that generate the service reference. For the sake of clarity, the following shows the definition of the method AddToDevLeapContacts:

public void AddToDevLeapContacts(DevLeapContactsItem devLeapContactsItem) {
    base.AddObject("DevLeapContacts", devLeapContactsItem);
}

Adding a new item to a list presents a code excerpt that adds an item to the sample list of contacts.

The sample code creates a new instance of an object with a type compliant with the target list. Then it sets the properties of the item (for instance, the fields) and adds it to the target list using the AddTo{ListName} method. Lastly, it invokes the SaveChanges method of the DataContext object to confirm the changes on the server side. Notice that the target list accepts two kinds of content types, so the sample also configures the ContentType property of the item in order to instruct SharePoint about the right content type to use on the server side.

The last common task in managing data is deleting entities. The DataContext class offers a DeleteObject method, which accepts an entity that will be marked to be deleted at the next SaveChanges invocation. Thus, to delete an item, you simply need to invoke SaveChanges, as Deleting an item from a list demonstrates.

The OData client library available in Visual Studio 2012 also provides full support for handling concurrency issues while managing data. However, it is beyond the scope of this chapter (and this book) to give you the proper coverage of the WCF Data Services Client Library. The key is understand the potential of this API while managing SharePoint data and external data in general whenever you have an OData provider available.

Summary

This chapter covered the client-side technologies offered by SharePoint 2013 with which you can query and manage data from a remote consumer. In particular, it discussed how to use the Client Object Model, together with its different flavors, such as the CSOM, the Silverlight Client Object Model, and the JSOM. It also covered how to use the REST service to query data—even with LINQ queries—and how to manage data. Now you are ready to develop SharePoint solutions and apps, armed with a solid understanding of the available tools and technologies.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset