Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Exploring SharePoint 2010 Client Object Model Capabilities

4.54/5 (29 votes)
5 Jan 2011CPOL21 min read 149.5K   1.6K  
This article talks about the powerful SharePoint 2010 Client Object Model Capabilities and various ways to utilize it.

Download Understanding SharePoint 2010 Client Object Model Capabilities - 5.29 MB

Introduction

SharePoint 2010 is really exciting and if you have already worked on the previous versions of SharePoint then needless to say that you will feel much more excited while exploring its new capabilities. Every platform has some drawbacks but the capabilities matter and we developers always like to explore the new things and feature that software or a platform offers. SharePoint 2010 has some fantastic and cool new features but unfortunately I did not get chance to work with all of those but managed myself to learn something about the Client Object Model in SharePoint 2010. In this article, I am trying to share what I have learnt till yet (still learning) about SharePoint 2010 Client Object Model. Complete source code are available in two projects that you can download and try to compile and execute at your end.

Welcome to SharePoint 2010 Client Object Model

If you have looked into the user interface of SharePoint 2010 then you may have noticed that Microsoft really enhanced the user experience by vastly minimizing page refreshes and using Silverlight. SharePoint required something new to fulfil its own demands for the improved user interface and to provide a better and more robust platform for creating solutions that will run off SharePoint servers. Client Object Model was introduced as one of the key capabilities to server this purpose. It helps developer to build client side applications that talk with SharePoint much more easily without using SharePoint Web Services and RPC calls.

What's wrong with SharePoint Web Services?

Following diagram depicts the flow of accessing data in MOSS 2007:

SP2010DATAFLOW.png

Earlier, you have to either use the Server Side Object Model or the Web Services or RPC calls to interact with MOSS 2007. Specially, if you want your Silverlight application to have data from SharePoint then you have to think and spend a lot of time to do so. Also, you can’t always use SharePoint Web Services as a solution because of the following reasons:

· XML based SOAP communications have marshalling and de-marshalling overheads.

  • Sessions are not authenticated and the all requests have to be authenticated (except OpenWorkbook method of ExcelServices web service).
  • Getting list of all site collections or web applications are not possible.
  • You can’t get the version of the SharePoint server.
  • Memory overhead while downloading files from SharePoint server.
  • There are limitations while retrieving item level permissions.

What's good about SharePoint 2010 Client Object Model?

Following diagram depicts the easier way to access SharePoint 2010 data using Client Object Model:

COMCLIENTS.png

There are lots of pluses as shown below:

· Simple API to perform CRUD operations within SharePoint 2010.
· Supports three major client development platforms

  • .NET Managed Object Model
  • ECMAScript Object Model (JavaScript)
  • Silverlight Client Object Model

· Consistent and strikingly similar implementations across three platforms.

· A better and richer user experience rather than having traditional asp.net post back driven user interface.

· Most of the processing happens on client machine thus reduces the impact on server.

· Calls are executed in batches to minimize the round trips.

· Asynchronous calls to ensure steady and responsive user experience.

· Similar constructs and naming conventions like server object model.

Mechanism behind SharePoint 2010 Client Object Model

 

Following diagram shows the basic mechanism that works behind the SharePoint Client Object Model:

COMMECHANISMS.png

 

If you use the API (Application Programming Interface) to access SharePoint 2010 data then the request gets packaged into XML format by the SharePoint Client Object Model and then the XML request is sent to the server. Server receives the request, parses and calls the SharePoint Server Object Model. Then it collects the response, parses and bundles in a JSON (JavaScript Object Notation) object and send it back to the SharePoint Managed Client Object Model. SharePoint Managed Client Object Model parses the JSON result it and then sends back to the .NET Managed Object Model or ECMA Script Model. Please take a look at the diagram shown above.

Flavours of SharePoint 2010 Client Object Model

 

SharePoint client object model comes in three flavours. For .NET Client applications, there is a .NET Managed Object Model is available. Silverlight applications can use Silverlight Client Object Model and for JavaScript implementations, ECMAScript Object Model can be used. Because of these three models, rich of the application goes higher, development becomes easier and client applications don’t need to depend on SharePoint Web Services and RPC calls.

Client Side classes and their equivalent server side classes:

Server Side Classes

Client Side Classes

SPContext

ClientContext

SPSite

Site

SPWeb

Web

SPList

List

SPListItem

ListItem

SPField

Field

.NET Managed Client Object Model

 

Open Visual Studio 2010 and create a new Empty SharePoint Project. Give a meaningful name and specify the path where the project will be created:

MCOMADDPROJECT.png

Specify the site where the application is going to be debugged. Remember to select “Deploy as a farm solution” option as Visual Web Parts cannot be used with sandbox solutions. Click on Finish to create the new project:

MCOMDEBUGSETTINGS.png

 

Next step is to add a Visual Web Part into the project. Specify the name of the Visual Web Part as “ClientOMWebPart”.

MCOMADDWEBPART.png

 

In the ascx file of the Visual Web Part, add the following code snippets:

 

Complete source code is available in the downloadable projects

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %> 
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="UIDemoUserControl.ascx.cs" Inherits="ClientOMUIActions.UIDemo.UIDemoUserControl" %>
<style type="text/css">
    .style1
    {
        height: 23px;
    }
    .style2
    {
        height: 25px;
    }
</style>
<script type="text/javascript">
    //Dialog opening 
    function OpenListDialog() {
        var options = SP.UI.$create_DialogOptions();
        options.url = "/_layouts/ClientOMUIActions/ListCreationPage.aspx";
        options.width = 600;
        options.height = 160;
        options.dialogReturnValueCallback = Function.createDelegate(null, CloseListCallback);
        SP.UI.ModalDialog.showModalDialog(options);
    }
    function OpenAllListsDialog() {
        var options = SP.UI.$create_DialogOptions();
        options.url = "/_layouts/ClientOMUIActions/ListViewerPage.aspx";
        options.width = 600;
        options.height = 500;
        options.dialogReturnValueCallback = Function.createDelegate(null, CloseListCallback);
        SP.UI.ModalDialog.showModalDialog(options);
    }
    function OpenDocLibDialog() {
        var options = SP.UI.$create_DialogOptions();
        options.url = "/_layouts/ClientOMUIActions/DocumentLibraryCreationPage.aspx";
        options.width = 600;
        options.height = 160;        
        options.dialogReturnValueCallback = Function.createDelegate(null, CloseDocLibCallback);
        SP.UI.ModalDialog.showModalDialog(options);
    }
    function OpenAsyncDialog() {
        var options = SP.UI.$create_DialogOptions();
        options.url = "/_layouts/ClientOMUIActions/AsynchronusProcessing.aspx";
        options.width = 800;
        options.height = 700;
        options.dialogReturnValueCallback = Function.createDelegate(null, CloseDocLibCallback);
        SP.UI.ModalDialog.showModalDialog(options);
    }
    
    function OpenCAMLDialog() {
        var options = SP.UI.$create_DialogOptions();
        options.url = "/_layouts/ClientOMUIActions/UsingCAMLQuery.aspx";
        options.width = 800;
        options.height = 700;
        options.dialogReturnValueCallback = Function.createDelegate(null, CloseDocLibCallback);
        SP.UI.ModalDialog.showModalDialog(options);
    }
    function OpenLINQDialog() {
        var options = SP.UI.$create_DialogOptions();
        options.url = "/_layouts/ClientOMUIActions/UsingLINQQuery.aspx";
        options.width = 800;
        options.height = 700;
        options.dialogReturnValueCallback = Function.createDelegate(null, CloseDocLibCallback);
        SP.UI.ModalDialog.showModalDialog(options);
    }
    function OpenSilverlightDialog() {
        var options = SP.UI.$create_DialogOptions();
        options.url = "/SitePages/SilverlightWebPartOM.aspx";
        options.width = 600;
        options.height = 400;
        options.dialogReturnValueCallback = Function.createDelegate(null, CloseDocLibCallback);
        SP.UI.ModalDialog.showModalDialog(options);
    }    
    var messageId;
    // Dialog callback 
    function CloseListCallback(result, target) {
        if (result === SP.UI.DialogResult.OK) {
            javascript: setTimeout('javascript:return true;', 8000); 
            messageId = SP.UI.Notify.addNotification("<img src='_layouts/images/loading.gif'> Creating list <b>" + target + "</b>..."); 
            //alert("OK was clicked!");
        }
        if (result === SP.UI.DialogResult.cancel) {
            //alert("Cancel was clicked!");
            SP.UI.Notify.addNotification("Operation was cancelled...", false, "", null); 
        }
    }
    function CloseDocLibCallback(result, target) {
        if (result === SP.UI.DialogResult.OK) {
            javascript: setTimeout('javascript:return true;', 8000);
            messageId = SP.UI.Notify.addNotification("<img src='_layouts/images/loading.gif'> Creating document library <b>" + target + "</b>...");
            //alert("OK was clicked!");
        }
        if (result === SP.UI.DialogResult.cancel) {
            //alert("Cancel was clicked!");
            SP.UI.Notify.addNotification("Operation was cancelled...", false, "", null);
        }
    }
</script>
<table bgcolor="#83BB00" border="0" cellpadding="3" cellspacing="3">
<tr>
<td colspan="4">
<b>Using Client Object Model in SharePoint 2010</b>
</td>
</tr>
<tr>
<td class="style1">
     </td>
<td class="style1">
</td>
<td class="style1">
     </td>
<td class="style1">
     </td>
</tr>
<tr>
<td>
    <strong>.NET MANAGED</strong></td>
<td>
    <strong>ECMASCRIPT</strong></td>
<td>
    <strong>SILVERLIGHT CLIENT</strong></td>
<td>
     </td>
</tr>
<tr>
<td>
    <a href="Javascript:OpenAsyncDialog();">Asynchronus Processing</a>
</td>
<td>
<a href="Javascript:OpenListDialog();">Create a List </a> 
</td>
<td>
    <a href="Javascript:OpenSilverlightDialog();">Using Asynchronus Client Object Model</a> </td>
<td>
     </td>
</tr>
<tr>
<td>
    <a href="Javascript:OpenCAMLDialog();">Using CAML Query</a>
</td>
<td>
<a href="Javascript:OpenDocLibDialog();">Create a Document Library </a> 
</td>
<td>
     </td>
<td>
     </td>
</tr>
<tr>
<td>
    <a href="Javascript:OpenLINQDialog();">Using LINQ with Queries</a></td>
<td>
     </td>
<td>
     </td>
<td>
     </td>
</tr>
</table>


Build the project, deploy and run the Visual Web Part by pressing F5 key on Visual Studio. Add the custom Visual Web Part on the page from the Web Part Gallery. The Visual Web Part will be opened like as shown below:

MCOMVIEWWEBPART.png

I have used ASP.NET Update Panel to avoid page flickering and full post back and the Update Progress control to show that the processing is in happening. Go to ISAPI folder under 14 hives and then add reference of the following assemblies in your project:

Microsoft.SharePoint.Client.dll Microsoft.SharePoint.Client.Runtime.dll

MCOMADDCAMLQUERYADDREF.png

Also the class must inherit from Microsoft.SharePoint.Client namespace. Then handle the btnCAMLQuery_Click event where we will be accessing the SharePoint server using the Client Object Model.

Client Context

It is the entry point to do programming with SharePoint Client Object Model. It works like the same as SPContext does and it ensures that there is a single object as a starting point for working with the client object model. ClientContext class inherits from IDisposable interface and thus you need to use the using statement or need to explicitly call IDisposable to dispose ClientContext object. If you don’t do so then you may run into memory leaks issues. Let us look into the properties and methods of the ClientContext class:

Name

Description

Dispose

Upon calling, this method disposes ClientContext object.

ExecuteQuery

When all the queries of the site are loaded this method can be called to send the commands to the server.

executeQueryAsync

This is available in the ECMAScript object model and it allows you to execute a query and pass tow delegates for the call back. One is used when the query returns success and the other one is used when query returns an error.

Load

Using the method syntax of LINQ, you can load your query using this method. Object can also be passed without a query which itself will return the object.

LoadQuery

This method can be used to return a collection of objects as an IQueryable collection. It also supports the method and query sytax forLINQ.

AuthenticationMode

There are three authentication modes available:

Default – This is a default on and then Managed Client Object Model authenticates the users using Windows credentials (NTLM and Kerberos).

Anonymous – If the site allows anonymous users then you can use this authentication mode.

FormsAuthentication – If the site uses form based authentication then this mode can be used. In the ClientContext instance, user credentials have to get supplied. Authentication cookie is used by the authentication web service before requesting the object.

FormsAuthenticationLoginInfo

In case of Forms Authentication, this property can be used to set the user id and password.

RequestTimeout

Gets or sets the timeout for the client request.

Site

Gets the site collections associated with the ClientContext class.

URL

Gets the URL of the site associated with the ClientContext class.

Web

Gets the website that the ClientContext is associated with.

The following code creates an instance of the ClientContext class for the mentioned site. The ClientContext object takes the URL parameter as it’s constructor to connect to any site collection or web. Then the authentication mode is set to default which is windows authentication:

C#
using (SP.ClientContext ctx = new SP.ClientContext("<a href="http://spdev/">http://SPDEV</a>"))
{
     ctx.AuthenticationMode = SP.ClientAuthenticationMode.Default;
}


In case you need the forms authentication then you can set the FormsAuthenticationLoginInfo property as shown below.

C#
ctx.AuthenticationMode = SP.ClientAuthenticationMode.FormsAuthentication;
SP.FormsAuthenticationLoginInfo formsAuthInfo = new SP.FormsAuthenticationLoginInfo("sanjay.santra", "<a href="mailto:p@s#54?&67");ctx.FormsAuthenticationLoginInfo">p@s#54?&67");
ctx.FormsAuthenticationLoginInfo</a> = formsAuthInfo;

Following code snippet shows how to use anonymous authentication:

C#
ctx.AuthenticationMode = SP.ClientAuthenticationMode.Anonymous;

Then we will create an object of the ClientContext.Web class. Next thing is to get the Announcements list. By looking into the implementation, it can be easily understood that it’s quite similar with the server side coding.

C#
var web = ctx.Web;
SP.List list = web.Lists.GetByTitle("Announcements");

Next step is to build the CAML Query. We have built a CAML Query as shown above which fetches list items from Announcement List and those items should not be expired. Microsoft.SharePoint.Client.CamlQuery class specifies a query on a list. ViewXml method Gets or sets value that specifies the XML schema that defines the list view. Microsoft.SharePoint.Client.List.GetItems method gets all items based on the CAML query set.

C#
SP.CamlQuery camlQuery = new SP.CamlQuery();
                camlQuery.ViewXml = @"
                                    <View>
                                        <Query>
                                            <Where>
                                                <And>
                                                     <IsNotNull>
                                                        <FieldRef Name='Title' />
                                                     </IsNotNull>
                                                     <Leq>
                                                        <FieldRef Name='Expires' />
                                                        <Value Type='DateTime'>2010-12-05T00:00:00Z</Value>
                                                     </Leq>
                                                </And>
                                            </Where>
                                        </Query>
                                    </View>";
SP.ListItemCollection listCollection = list.GetItems(camlQuery);

Then it is the time to load the query by calling the ClientContext.Load method and passing the ListItemCollection as parameter. Then the ClientContext.ExecuteQuery method is called which sends the command to server and executes the CAML Query that we set.

C#
ctx.Load(listCollection);
ctx.ExecuteQuery();

The next step is to populate a data table and binding it to a SPGridView:

C#
DataTable dTable = new DataTable();
dTable.Columns.Add("ID");
dTable.Columns.Add("Title");
dTable.Columns.Add("Created");
dTable.Columns.Add("Modified");
dTable.Columns.Add("CreatedBy");
dTable.Columns.Add("ModifiedBy");
dTable.Columns.Add("Expires");
for (int iCntr = 0; iCntr < listCollection.Count; iCntr++)
 {
      dTable.Rows.Add(dTable.NewRow());
      dTable.Rows[dTable.Rows.Count - 1]["ID"] = listCollection[iCntr]["ID"].ToString();
      dTable.Rows[dTable.Rows.Count - 1]["Title"] = listCollection[iCntr]["Title"].ToString();
      dTable.Rows[dTable.Rows.Count - 1]["Created"] = listCollection[iCntr]["Created"].ToString();
      dTable.Rows[dTable.Rows.Count - 1]["Modified"] = listCollection[iCntr]["Modified"].ToString();
      dTable.Rows[dTable.Rows.Count - 1]["CreatedBy"] = ((Microsoft.SharePoint.Client.FieldUserValue)(listCollection[iCntr]["Author"])).LookupValue;
      dTable.Rows[dTable.Rows.Count - 1]["ModifiedBy"] = ((Microsoft.SharePoint.Client.FieldUserValue)(listCollection[iCntr]["Editor"])).LookupValue;
      dTable.Rows[dTable.Rows.Count - 1]["Expires"] = listCollection[iCntr]["Expires"].ToString();
}
if (dTable.Rows.Count > 0)
{
      spGrdMain.DataSource = dTable;
      spGrdMain.DataBind();
}
else
{
      dTable.Rows.Add(dTable.NewRow());
      dTable.Rows[dTable.Rows.Count - 1]["ID"] = "Query returned zero results.";
}

Finally, it’s time to run the page. Press F5 to start debugging and in the web part page click on “Using CAML Query” link.

MCOMADDCAMLQUERYRUN1.png

Click on “Get Data Using CAML Query” button to fire the CAML Query.

 MCOMADDCAMLQUERYVIEW.png

The returned result will be shown in the SPGridView as shown below.

 MCOMADDCAMLQUERYRUN2.png

Using LINQ with Queries

Add another Application Page and name it UsingLINQQuery.aspx. Add a button and a label control which can be wrapped with an update panel (not mandatory). Also, add an update progress control. You can use the following code in your aspx file:

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="UsingLINQQuery.aspx.cs" Inherits="ClientOMUIActions.Layouts.ClientOMUIActions.UsingLINQQuery" DynamicMasterPageFile="~masterurl/default.master" %>
<asp:Content ID="PageHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
<asp:UpdateProgress ID="updProgress" AssociatedUpdatePanelID="updMain" runat="server">
    <ProgressTemplate>
        <table>
        <tr>
        <td>
         Loading data using LINQ query with SharePoint Managed Client Object Model...
        </td>
        <td>
        <img src="http://www.codeproject.com/_layouts/ClientOMUIActions/Images/Loader1.gif" />
        </td>
        </tr>
        </table>
        </div>
    </ProgressTemplate>
</asp:UpdateProgress>
<asp:UpdatePanel ID="updMain" runat="server">
<ContentTemplate>
<asp:Button class="ms-ButtonHeightWidth" ID="btnLINQQuery" runat="server" Text="Get Data Using CAML Query" OnClick="btnLINQQuery_Click"/>                    
    <asp:Label ID="lblLists" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
</asp:Content>
<asp:Content ID="PageTitle" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
:::Using LINQ Query with .NET Managed Client Object Model:::
</asp:Content>
<asp:Content ID="PageTitleInTitleArea" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server" >
:::Using LINQ Query with .NET Managed Client Object Model:::
</asp:Content>

Class must inherit from Microsoft.SharePoint.Client namespace. Then handle the btnLINQQuery_Click event where we will be accessing the SharePoint server using the Client Object Model. You can get the complete code from the downloadable sample project. Most of the things are the same as I described earlier (for CAML Query), so I am directly coming into the section where you need to define the LINQ Query:

C#
SP.List list = web.Lists.GetByTitle("Announcements");
var query = from listNew
            in web.Lists
            where listNew.Title != null                            
            select listNew;
var listCollection = ctx.LoadQuery(query);
ctx.ExecuteQuery();


Here, I have created one LINQ query which fetches data from the Announcements list and put it in a variable. Then the LINQ query can be passed by using the LoadQuery method. Finally, ExecuteQuery method is called to execute the query and iterate through the results. Then we can bind the collection to the label control that we have used for this purpose.

C#
foreach (SP.List resList in listCollection)
{
    lblLists.Text += "</br>" + resList.Title;
}

The final output will be something like as shown below:  nMCOMADDLINQQUERYRUN.png

Asynchronous Processing

Two programs that we developed are all synchronous. The problem with synchronous code is that the application becomes unresponsive when an operation is taking place. Until the operation gets completed, users need to wait to use the application. This problem happens particularly with .NET Managed Clients but not with Silverlight and ECMAScript because those are asynchronous in nature by default. Add a new Application Page in the project. Name it as AsynchronousProcessing.aspx. Add the following code inside the aspx page:

<asp:UpdateProgress ID="updProgress" AssociatedUpdatePanelID="updMain" runat="server">
    <ProgressTemplate>
        <table>
        <tr>
        <td>
         Loading data asynchronusly using SharePoint Managed Client Object Model...
        </td>
        <td>
        <img src="http://www.codeproject.com/_layouts/ClientOMUIActions/Images/Loader1.gif" />
        </td>
        </tr>
        </table>
        </div>
    </ProgressTemplate>
</asp:UpdateProgress>
<asp:UpdatePanel ID="updMain" runat="server">
<ContentTemplate>
<table class="style1">
            <tr>
                <td colspan="5">
                    <asp:Button class="ms-ButtonHeightWidth" ID="btnAsync" runat="server" Text="Get All Data Asynchronusly" OnClick="btnAsync_Click"/>                    
                </td>                
            </tr>
            <tr>
                <td style="background-color:Silver;">
                    <b>Available Lists</b></td>
                <td style="background-color:Silver;">
                    <b>Available List Templates</b>
                </td>
                <td style="background-color:Silver;">
                    <b>Available Fields</b></td>
                <td style="background-color:Silver;">
                    <b>Available Folders</b></td>
                <td style="background-color:Silver;">
                    <b>Available Role Definitions</b></td>
                <td style="background-color:Silver;">
                    <b>Available Feature Definitions</b></td>
            </tr>
            <tr>
                <td valign="top">
                    <asp:Label ID="lblLists" runat="server"></asp:Label>
                </td>
                <td valign="top">
                    <asp:Label ID="lblListTemplates" runat="server"></asp:Label>
                </td>
                <td valign="top">
                    <asp:Label ID="lblFields" runat="server"></asp:Label>
                </td>
                <td valign="top">
                    <asp:Label ID="lblFolders" runat="server"></asp:Label>
                </td>
                <td valign="top">
                    <asp:Label ID="lblRoles" runat="server"></asp:Label>
                </td>
                <td valign="top">
                    <asp:Label ID="lblFeatures" runat="server"></asp:Label>
                </td>
            </tr>
        </table>
        </ContentTemplate>
</asp:UpdatePanel>

Implementation is almost similar like the other two demonstrations except main change that you need to do is to use the BeginInvoke method of the IAsyncResult interface. Define a class level delegate of type string.


Class must inherit from Microsoft.SharePoint.Client namespace. Then handle the btnAsync_Click event where we will be accessing the SharePoint server using the Client Object Model. You can get the complete code from the downloadable sample project.

C#
delegate string AsynchronousDelegate();

Basically in this demonstration, I am going to fetch all the lists, list templates, fields, folders, role definitions and feature definitions that are available in the site. Populating all these items takes time and that is why we need an asynchronous processing which helps to maintain the responsiveness in the page. The code is shown below:

C#
AsynchronousDelegate executeQueryAsynchronouslyLists = null;
IAsyncResult asyncResultLists = null;

AsynchronousDelegate executeQueryAsynchronouslyListTemplates = null;
IAsyncResult asyncResultListTemplates = null;

AsynchronousDelegate executeQueryAsynchronouslyFields = null;
IAsyncResult asyncResultFields = null;

AsynchronousDelegate executeQueryAsynchronouslyFolders = null;
IAsyncResult asyncResultFolders = null;

AsynchronousDelegate executeQueryAsynchronouslyRoles = null;
IAsyncResult asyncResultRoles = null;

AsynchronousDelegate executeQueryAsynchronouslyFeatures = null;
IAsyncResult asyncResultFeatures = null;
try
{
    executeQueryAsynchronouslyLists = new AsynchronousDelegate(GetLists);
    asyncResultLists = executeQueryAsynchronouslyLists.BeginInvoke(null, null);

    executeQueryAsynchronouslyListTemplates = new AsynchronousDelegate(GetListTemplates);
    asyncResultListTemplates = executeQueryAsynchronouslyListTemplates.BeginInvoke(null, null);

    executeQueryAsynchronouslyFields = new AsynchronousDelegate(GetFields);
    asyncResultFields = executeQueryAsynchronouslyFields.BeginInvoke(null, null);

    executeQueryAsynchronouslyFolders = new AsynchronousDelegate(GetFolders);
    asyncResultFolders = executeQueryAsynchronouslyFolders.BeginInvoke(null, null);

    executeQueryAsynchronouslyRoles = new AsynchronousDelegate(GetRoles);
    asyncResultRoles = executeQueryAsynchronouslyRoles.BeginInvoke(null, null);

    executeQueryAsynchronouslyFeatures = new AsynchronousDelegate(GetFeatures);
    asyncResultFeatures = executeQueryAsynchronouslyFeatures.BeginInvoke(null, null);

    lblLists.Text = executeQueryAsynchronouslyLists.EndInvoke(asyncResultLists);
    lblListTemplates.Text = executeQueryAsynchronouslyListTemplates.EndInvoke(asyncResultListTemplates);
    lblFields.Text = executeQueryAsynchronouslyFields.EndInvoke(asyncResultFields);
    lblFolders.Text = executeQueryAsynchronouslyFolders.EndInvoke(asyncResultFolders);
    lblRoles.Text = executeQueryAsynchronouslyRoles.EndInvoke(asyncResultRoles);
    lblFeatures.Text = executeQueryAsynchronouslyFeatures.EndInvoke(asyncResultFeatures);
}
catch(Exception pEx)
{
    lblLists.Text = pEx.ToString();
}
finally
{                
    executeQueryAsynchronouslyLists = null;
    asyncResultLists = null;

    executeQueryAsynchronouslyListTemplates = null;
    asyncResultListTemplates = null;

    executeQueryAsynchronouslyFields = null;
    asyncResultFields = null;

    executeQueryAsynchronouslyFolders = null;
    asyncResultFolders = null;

    executeQueryAsynchronouslyRoles = null;
    asyncResultRoles = null;

    executeQueryAsynchronouslyFeatures = null;
    asyncResultFeatures = null;
}

We are passing the name of the method into the delegate object and it will be executed asynchronously. Then an object of the IAsyncResult interface is created which is initialized with the BeginInvoke method of the delegate. It is the return type of methods that initiate an asynchronous operation. BeginInvoke adds the operation to a queue, where it is then serviced by a separate thread from a Common Language Runtime (CLR) managed thread pool. The EndInvoke method gets the result of the asynchronous call. If you are using BeginInvoke then you should use EndInvoke which confirms result of the operation that is fired by BeginInvoke. A BeginInvoke without an EndInvoke may cause memory leaks. Finally, the label controls can be bound with the result returned by the EndInvoke method. The calling methods are relative simpler as we already showed how to do the .NET Managed Client Object Model calls to SharePoint. But, I am showing one method just for the reference:

C#
protected string GetListTemplates()
{
     using (SP.ClientContext ctx = new SP.ClientContext("<a href="http://spdev/">http://SPDEV</a>"))
     {
         ctx.AuthenticationMode = SP.ClientAuthenticationMode.Default;
         string returnValue = string.Empty;
         var web = ctx.Web;
         ctx.Load(web);              
         ctx.Load(web.ListTemplates);               
         ctx.ExecuteQuery();
         SP.ListTemplateCollection lists = web.ListTemplates;
         ctx.ExecuteQuery();
         foreach (SP.ListTemplate list in lists)
               returnValue += "</br>" + list.Name;
         return returnValue;
     }
}
 


Please refer the provided code and when the page will run it will look like as shown below:


MCOMASYNCRUN.png

 MCOMASYNCRUN1.png

ECMAScript Client Object Model

Working with ECMAScript with Client Object Model is relatively simpler and similar if you have already worked with .NET Managed Client Object Model. But there are few differences which are shown below:

• You can’t use server side urls in the ClientContext constructor.

• It does not support LINQ syntax.

• It is asynchronous in nature.

• A FormDigest control has to be included to create a digest for security validations when performing some modifications to SharePoint data. It adds a security token inside your page based on user, site and time. Once the page is posted back the security token is validated. Once the security token is generated it’s valid for a configurable amount of time. To know more about it, please go through this link:

http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.formdigest.aspx

Let us do some hands on using ECMAScript. Add an Application Page into the project with any name but in the downloadable code I have named it as “ListCreationPage.aspx”. In this demonstration, we are going to create a SharePoint 2010 list by using ECMAScript Client Object Model. So to do that, add the following code snippets in the aspx page:

<asp:Content ID="PageHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
<script type="text/javascript"> 
    var messageId;
    function BtnCreateListCancel_Click() { 
       SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, 'Cancelled clicked'); 
    } 
    function BtnCreateListOk_Click() { 
        var form = document.forms.<%SPHttpUtility.NoEncode(Form.ClientID,Response.Output);%>; 
        var ListNameUrl = form.<%SPHttpUtility.NoEncode(TxtListName.ClientID,Response.Output);%>.value; 
        
        //Create list using client OM 
        createList(ListNameUrl);
        SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, ListNameUrl); 
    } 
    //Actual JS client side object model calls 
function createList(listName) { 
    //Create client context. 
    var clientContext = new SP.ClientContext(); 
    var oWebsite = clientContext.get_web(); 
    //Let's create list creation information object 
    var listCreationInfo = new SP.ListCreationInformation(); 
    listCreationInfo.set_title(listName); 
    listCreationInfo.set_templateType(SP.ListTemplateType.announcements); 
    listCreationInfo.set_quickLaunchOption(SP.QuickLaunchOptions.on); 
    this.oList = oWebsite.get_lists().add(listCreationInfo); 
    //Let's create also new item to the list to be created 
    var itemCreateInfo = new SP.ListItemCreationInformation(); 
    this.oListItem = oList.addItem(itemCreateInfo); 
    oListItem.set_item('Title', 'Example item for ' + listName); 
    oListItem.set_item('Body', 'Hello seminar audience. From list ' + listName); 
    oListItem.update(); 
    clientContext.load(oListItem); 
    clientContext.load(oList); 
    //Execute the actual script 
    clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed)); 
} 
//Called if client side OM is successful 
function onQuerySucceeded() { 
    //Remove the 'creating' event notification 
    if(messageId != null)
    {
        SP.UI.Notify.removeNotification(messageId); 
    }
    //Add 'created' notification as non sticky 
    messageId = SP.UI.Notify.addNotification("List <b>" + oList.get_title() + "</b> created...", false, "", null); 
} 
function onQueryFailed(sender, args) { 
    //Remove the 'creating' event notification 
    if(messageId != null)
    {
        SP.UI.Notify.removeNotification(messageId); 
    }
    //Shown in case of error on the JS OM call 
    messageId = SP.UI.Notify.addNotification("Operation was cancelled...", false, "", null); 
} 
</script>
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
<table id="maintable" border="0" cellspacing="0" cellpadding="0" class="ms-propertysheet" width="100%"> 
    <tr>
    <td>    
      <wssuc:InputFormSection Title="List name" runat="server"> 
        <Template_Description> 
          <SharePoint:EncodedLiteral ID="EncodedLiteral1" runat="server" text="Define list name to be created." EncodeMethod='HtmlEncode'/> 
        </Template_Description> 
        <Template_InputFormControls> 
          <wssuc:InputFormControl runat="server"> 
            <Template_Control> 
              <table border="0" cellspacing="1"> 
                <tr> 
                  <td class="ms-authoringcontrols" colspan="2" nowrap="nowrap"> 
                    <SharePoint:EncodedLiteral ID="EncodedLiteral7" runat="server" text="List name will be used as url and as the title" EncodeMethod='HtmlEncode'/>: 
                    <font size="3">&#160;</font><br /> 
                  </td> 
                </tr> 
                <tr> 
                  <td dir="ltr"> 
                  <table> 
                      <tr> 
                      <td>
                          <tdnowrap="nowrap"colspan="2"class="ms-authoringcontrols"> 
                            <wssawc:InputFormTextBox title="Enter list name" class="ms-input" ID="TxtListName" Columns="35" Runat="server" maxlength="255" size="60" width="100%" /> 
                          </td> 
                      </tr> 
                  </table> 
                  </td> 
                </tr> 
              </table> 
            </Template_Control> 
          </wssuc:InputFormControl> 
        </Template_InputFormControls> 
      </wssuc:InputFormSection> 
      <wssuc:ButtonSection runat="server" ShowStandardCancelButton="False"> 
        <Template_Buttons> 
          <asp:placeholder ID="Placeholder1" runat="server"> 
          <input class="ms-ButtonHeightWidth" type="button" name="BtnOk" id="Button1" value="OK" onclick="BtnCreateListOk_Click()"  /> 
            <SeparatorHtml> 
                <span id="idSpace" class="ms-SpaceBetButtons" /> 
            </SeparatorHtml> 
          <input class="ms-ButtonHeightWidth" type="button" name="BtnCancel" id="Button2" value="Cancel" onclick="BtnCreateListCancel_Click()" />            
          </asp:PlaceHolder> 
        </Template_Buttons> 
      </wssuc:ButtonSection> 
      </td>
    </tr>
    </table> 
</asp:Content>

Include references to SP.js, SP.Debug.js. Please note that don’t include SP.Debug.js if it is going to be used in production environment. We are having one SharePoint InputFormTextBox control and the button control. To create a list, user has to specify the name of the list into the InputFormTextBox control and click on the “Ok” button. So, we need to attach a JavaScript function named BtnCreateListOk_Click(). Definition of this function is shown below:

C#
function BtnCreateListOk_Click() 
{ 
        var ListNameUrl = form.<%SPHttpUtility.NoEncode(TxtListName.ClientID,Response.Output);%>.value; 
        
        //Create list using client OM 
        createList(ListNameUrl);
        SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, ListNameUrl); 
}

First thing to do here is to get the name of the list which needs to be created. Use NoEncode method of the SPHttpUtility class to get the value of the InputFormTextBox control. Then we passed the name of list to the createList function. So, let’s go inside the createList function:

C#
function createList(listName) { 
    //Create client context. 
    var clientContext = new SP.ClientContext(); 
    var oWebsite = clientContext.get_web(); 
    //Let's create list creation information object 
    var listCreationInfo = new SP.ListCreationInformation(); 
    listCreationInfo.set_title(listName); 
    listCreationInfo.set_templateType(SP.ListTemplateType.announcements); 
    listCreationInfo.set_quickLaunchOption(SP.QuickLaunchOptions.on); 
    this.oList = oWebsite.get_lists().add(listCreationInfo); 
    //Let's create also new item to the list to be created 
    var itemCreateInfo = new SP.ListItemCreationInformation(); 
    this.oListItem = oList.addItem(itemCreateInfo); 
    oListItem.set_item('Title', 'Sample item for ' + listName); 
    oListItem.set_item('Body', 'Hi friends. From list ' + listName); 
    oListItem.update(); 
    clientContext.load(oListItem); 
    clientContext.load(oList); 
    //Execute the actual script 
    clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed)); 
} 
//Called if client side OM is successful 
function onQuerySucceeded() { 
    //Remove the 'creating' event notification 
    if(messageId != null)
    {
        SP.UI.Notify.removeNotification(messageId); 
    }
    messageId = SP.UI.Notify.addNotification("List <b>" + oList.get_title() + "</b> created...", false, "", null); 
} 
function onQueryFailed(sender, args) { 
    //Remove the 'creating' event notification 
    if(messageId != null)
    {
        SP.UI.Notify.removeNotification(messageId); 
    }
    //Shown in case of error on the JS OM call 
    messageId = SP.UI.Notify.addNotification("Operation was cancelled...", false, "", null); 
} 

First, we need to get the ClientContext object and then we can use the get_web() (just like SPContext.Current.Web) method of the SP.ClientContext object to get the associated web site. As we are going to create a list in this demonstration, so we have to create an object of the SP.ListCreationInformation class. We need to set the title, list template type and also have to specify whether the list will appear on the quick launch menu or not. Finally, we can add the list by calling get_lists().add method which takes the ListCreationInformation object as a parameter. After creating the list, let’s create one list item. Create an object of the ListItemCreation class and set the title and body accordingly. Call the update method to update the list item. Anyway, you have to call the load method to load the properties of the list and list item before you call the executeQueryAsync method. executeQueryAsync method executes asynchronously and takes two functions: onQuerySucceeded and onQueryFailed. If you will look into those functions then you will notice that those two functions are mainly used to handle the success and failure and presenting user defined error message using SharePoint 2010 enhanced UI notifications.

Discussing SharePoint 2010 enhanced UI notifications and Dialogs are not in the scope of our discussion so I am not going to discuss this in details. So, click on the “Create a List” link under ECMAScript section available on the Visual Web Part that we have added earlier. SharePoint 2010 UI Dialog will be opened and it will prompt you to type the list name. Once entered, click on OK to create the list:

 ECMARUNPAGE1.png

SharePoint 2010 status bar is updated with the process in progress:

ECMARUNPAGE2.png

Finally, you can go to the newly created list and find the default list item that we have created.

ECMARUNPAGE3.png

Silverlight Client Object Model

Silverlight Client Object Model can be used in two contexts. It can be used with in a Silverlight Web Part and it can also be used with in Silverlight cross domain data access system. Most of the things are quite similar as compared to .NET Managed Client Object Model but Silverlight does not support synchronous operations. So, you have to create delegates and also the success and failure methods. Also, the code runs on a background thread so the user interface thread needs to get on before anything can be written to it. So, the code has to be wrapped with the BeginInvoke method of the Dispatcher object. So, let’s create a Silverlight application which will retrieve all available lists under a SharePoint 2010 site. Open Visual Studio 2010 in Administrator mode. Create a new Silverlight Application. Name it “SilverlightOM”.


SILVERLIGHTADDPROJECT.png

You will be prompted to choose the Silverlight Version. Please select Silverlight 4. Also make sure that you have checked the “Host the Silverlight application in a new Web site” option so that a new web project will be created which will be hosting the Silverlight application. Click on OK to continue.

 SILVERLIGHTCHOOSEVERSION.png

When the project will be created, you will find two projects as shown below:

 SILVERLIGHTPROJECTVIEW.png

Now in the SilverlightOM project, add the references of the Microsoft.SharePoint.Client.Silverlight.dll and Microsoft.SharePoint.Client.Silverlight.Runtime.dll.

Now where do these assemblies exist? Actually, these are available in the following location: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ClientBin

 SILVERLIGHTPROJECTADDREF.png

Open the ManPage.xaml and put the following code:

<UserControl x:Class="SilverlightOM.MainPage"
    xmlns="<a href="http://schemas.microsoft.com/winfx/2006/xaml/presentation">http://schemas.microsoft.com/winfx/2006/xaml/presentation</a>"
    xmlns:x="<a href="http://schemas.microsoft.com/winfx/2006/xaml">http://schemas.microsoft.com/winfx/2006/xaml</a>"
    xmlns:d="<a href="http://schemas.microsoft.com/expression/blend/2008">http://schemas.microsoft.com/expression/blend/2008</a>"
    xmlns:mc="<a href="http://schemas.openxmlformats.org/markup-compatibility/2006">http://schemas.openxmlformats.org/markup-compatibility/2006</a>"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="500" xmlns:toolkit="<a href="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit</a>" xmlns:sdk="<a href="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk</a>">
   
        <Grid x:Name="LayoutRoot" Background="White" Height="300" Width="448">
            <Button Content="Get All Lists" Height="23" HorizontalAlignment="Left" Margin="12,54,0,0" Name="btnSilverlight" VerticalAlignment="Top" Width="97" Click="btnSilverlight_Click" />
        <ListBox Height="175" HorizontalAlignment="Left" Margin="12,91,0,0" Name="lbLists" VerticalAlignment="Top" Width="395" />
    </Grid>   
</UserControl>

In this demonstration, we are using a button and a list box control. On button click, list box will be populated with all the lists available in the site. Now as we have defined the controls in the code shown above, now it’s time to handle the button click event where we will write the code using Silverlight Client Object Model to retrieve data from a SharePoint 2010 Site. Also, add the following class level variable: Activities are almost same except the asynchronous way of handling the request. We have defined a ClientContext object. Then, we are querying the web to get all the lists. Now, we need to create two delegate objects; one is for handling request success event (ClientRequestSucceededEventHandler) and the other one is for request failure event (ClientRequestFailedEventHandler). Corresponding success and failure event handling functions have to be passed as parameters of the delegate objects. Now these delegate objects are required to be passed to the ExecuteQueryAsync method. Next thing to do is to define the two functions that we defined for the success and failure activities.

C#
IEnumerable<SP.List> listItems = null;
private void btnSilverlight_Click(object sender, RoutedEventArgs e)
{
     SP.ClientContext ctx = new SP.ClientContext("<a href="http://spdev/">http://SPDEV</a>");
     var query = from listCollection in ctx.Web.Lists
                     
     select listCollection;
     listItems = ctx.LoadQuery(query);
     SP.ClientRequestSucceededEventHandler success = new  SP.ClientRequestSucceededEventHandler(getItemsSucceeded);
     SP.ClientRequestFailedEventHandler failure = new SP.ClientRequestFailedEventHandler(getItemsFailed);
     ctx.ExecuteQueryAsync(success, failure);
}

C#
private void getRequestSucceeded(object sender, SP.ClientRequestSucceededEventArgs e)
{
    Dispatcher.BeginInvoke(() =>
    {
        lbLists.ItemsSource = listItems;
        lbLists.DisplayMemberPath = "Title";
    });
}
private void getRequestFailed(object sender, SP.ClientRequestFailedEventArgs e)
{
     Dispatcher.BeginInvoke(() =>
     {
          MessageBox.Show("Request failed with the following details: " + e.ErrorCode + " " + e.ErrorDetails + " " + e.Message + " " + e.StackTrace);
     });
}

So for both the methods, the code that makes changes in the user interface (UI) through the Silverlight object model, you must delegate this work to the Dispatcher object of the thread that created the UI by calling BeginInvoke method. In the code shown above, you can see that in the success function we are binding the list box with the list items and in case failure we are displaying a message box with the error details. Please note that if you directly try to update (without using BeginInvoke method) the user interface (UI), then you may receive the following error: “Invalid cross-thread access” Run the application and if everything is running fine then it is the time to run the application within SharePoint 2010 environment. So to do that, we need to use this application in a Silverlight 2010 Web Part.

ClientAccessPolicy.xml

If you need to use cross domain calls (Silverlight application is running in your domain but calling a service on other domain) then you must have to use clientaccesspolicy.xml file. Because, cross domain communication requires protection against multiple security threats. To elaborate a little, let assume that your Silverlight application is running on http://abcintranet.com/som and this application is trying to call a service on http://xyzintranet.com/pom/service.svc. This request will be prevented as there may be malicious Silverlight controls which are trying to perform an unauthorized operation by calling the service. Silverlight 4 supports two kinds of policy files for cross domain access: Place a ClientAccessPolicy.xml file at the root location of the domain where the service is hosted to configure the service to allow cross-domain access. Place a CrossDomain.xml file at the root location of the domain where the service is hosted. The file must mark the entire domain as public. In our case, we have to add a ClientAccessPolicy.xml file at the root location of the domain. Create the file with the following xml:

<?xml version="1.0" encoding="utf-8" ?>  
<access-policy>   
      <cross-domain-access>
            <policy>       
                  <allow-from http-request-headers="*">
                         <domain uri="*" /> 
                  </allow-from>
                  <grant-to>
                         <resource path="/" include-subpaths="true" /> 
                  </grant-to>
           </policy>
     </cross-domain-access>
</access-policy>

Build your Silverlight project and take out the .xap file. You can find it in the SilverlightOM.Web/ClientBin folder. Then upload the .xap file to a document library in the SharePoint 2010 site. Then Edit the SharePoint page and add a Silverlight Web Part. Specify the location of the .xap file which you have stored inside a document library. Click on OK and specify the other properties of this file which is optional.

SILVERLIGHTDEPLOY.png

So, Silverlight Web Part gets added into the page and on clicking the “Get All Lists” button, all available lists in the site will be displayed in the list box.

SILVERLIGHTRUN.png

Object equivalency across various SharePoint Object Models

Server Object Model

.NET Managed Client Object Model

ECMAScript Object Model

Microsoft.SharePoint.SPContext

Microsoft.SharePoint.Client.ClientContext

SP.ClientContext

Microsoft.SharePoint.SPSite

Microsoft.SharePoint.Client.Site

SP.Site

Microsoft.SharePoint.SPWeb

Microsoft.SharePoint.Client.Web

SP.Web

Microsoft.SharePoint.SPList

Microsoft.SharePoint.Client.List

SP.List

Microsoft.SharePoint.SPListItem

Microsoft.SharePoint.Client.ListItem

SP.ListItem

Microsoft.SharePoint.SPField

Microsoft.SharePoint.Client.Field

SP.Field

-

Microsoft.SharePoint.Client.ApplicationContext

-

-

-

SP.Application.UI

-

-

SP.Ribbon

-

-

SP.Ribbon.PageState

-

-

SP.Ribbon.TenantAdmin

-

-

SP.UI

-

-

SP.UI.ApplicationPages

-

-

SP.UI.ApplicationPages.Calendar

-

Microsoft.SharePoint.Client.Utilities

SP.Utilities

-

Microsoft.SharePoint.Client.WebParts

SP.WebParts

-

Microsoft.SharePoint.Client.Workflow

SP.Workflow

Ending Notes

My intention behind writing this article is to give a very basic level of understanding of how SharePoint Client Object Model works. Also, I have tried to unite maximum no of easy procedures and methodologies to implement the same. SharePoint Client Object Model is really powerful and convenience and one should know it. Entire source code is available in form of two projects that can be downloaded.

Learning is a never ending process and whatever I learned in recent few weeks I thought I should share it. Starters will get the start and experts are more than welcome to share their ideas or inputs if anything is missed out or something needs to be changed. You may agree with me that writing is a tough job for a developer and indeed it was for me. It’s been two weeks since I am staying back late in office to finish up with the article apart from my regular work.

This article is for all of my team mates and you all. I will be pleased to know if this article becomes useful for you. I will be more than happy to get your questions, feedbacks, suggestions and advices. Write to me at: SanjaySantra@hotmail.com . Happy reading to you all!

References

http://msdn.microsoft.com/en-us/library/ee857094(office.14).aspx

http://msdn.microsoft.com/en-us/library/cc197955(v=vs.95).aspx

http://blogs.technet.com/b/vedant/archive/2010/06/14/sharepoint-2010-resource-guide.aspx

http://blogs.msdn.com/b/vesku/archive/2010/02/25/how-to-sharepoint-2010-js-client-object-model-and-ui-advancements.aspx

http://www.zimmergren.net/archive/2009/11/30/sp-2010-getting-started-with-the-client-object-model-in-sharepoint-2010.aspx

Professional SharePoint 2010 Development by Tom Rizzo, Reza AliRezai, Paul J Swider, Scott Hiller, Jeff Fried & Kenneth Schaefer

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)