SharePoint 2013 CSOM and REST Improvements


I still remember back in the time of SharePoint 2007 and before the only way to create Applications for SharePoint was either use the Server Side Object Model or SOAP based web services.  Server side object mode was great but not having the ability to run out of SharePoint Server made is limited for SharePoint web parts and custom console application only.  Web services were there but they were not enough for everything that we need and as everything was XML it was sometimes very difficult to control and extend.  I still remember that I was part of the team that developed a project that uses SharePoint Lists Web Services to get and set data from Biztalk and Project Server and I have to build classes to build CAML and ViewFields.

SharePoint 2010 came up of couple of great ways to extend application development possibilities.  The Client Object Model and REST based listdata.svc made it possible to develop remote applications for SharePoint. 

There are three flavors of Client OM in SharePoint 2010.

  • .NET Managed Client OM
  • Silverlight Managed Client OM
  • JavaScript Client OM

It is important to know that the backbone of SharePoint Client OM was client.svc.  The service which was commonly reffered as WCF Entry point was response for executing the code that you write using the proxy writing using either of the above flavors.  The code is passed to client.svc as XMLhttpRequest execution happens as Batch.  client.svc handles the serilization and parsing of replies.  Once finished processing the response is send as JSON.

Managed Client OM.

NET Client Object Model and Silverlight Client OM were almost same in the implementation and to use .NET Client OM from either a Windows or Console application you have to add references to two Microsoft.SharePoint.Client and Microsoft.SharePoint.Client.Runtime and then write the proxy code which will later executed by client.svc.  Remember that code is Client OM can execute Synchronously.

You call ClientContext.ExecuQuery() method.

Silverlight Client OM

The difference with Silverlight was the difference of DLLs. The SharePoint Root Folder Client Bin folder had two Silverlight Client Dlls that you have to add to your Silverlight Class library.  The implementation is almost same other than the fact calls to SharePoint from Silverlight must be done using asynchronously callback. 

You call ClientContext.ExecuQueryAsync(SucessDelegate, FailureDelegate); method.

JavaScript Client OM.

The third and final way of writing client side applications for SharePoint is/was JavaScript OM.  JavaScript Client OM uses SP.JS, SP.Core.JS files which contains the proxy implementation calls to client.svc.  The pattern or writing the app was same but there was difference between Windows/Silverlight and JavaScript by JavaScript using methods instead of properties and method name used in JavaScript were not same.  JS Client OM works perfectly with jQuery, JSRender and other libraries and provide support for Atom & oData standards.

By far JavaScript client OM was the most difficult way of writing SharePoint applications. Reason was Visual Studio providing strongly typed object, type checking and debug support for SharePoint objects while for debugging in JS OM we have to live with debugging in IE Developer tools only.  The place where I was during the 2010 implementation time frame I saw few people developing anything in JavaScript. 

One of the major drawbacks of Client Object Model in SharePoint was limited access to SharePoint functionality. 

image

Client Object Model Changes in SharePoint 2013

Although the overall architecture of Client OM in SharePoint 2013 remains the same but there are some major improvement.  The biggest improvement is that the all time hidden Client.svc is directly available for developers to make REST calls to do Get and POST Requests.  Client.svc implements the core features of OData specifications.  For more information please visit www.odata.org or http://msdn.microsoft.com/en-us/library/fp142385.aspx.  Please note that you can continue to use the 3 traditional methods to reach SharePoint Data.

SharePoint 2013 Client OM Extends reach to SharePoint Data by providing access to

  • User Profiles
  • Search
  • Social Feeds
  • Sharing
  • BCS
  • IRM
  • Analytics
  • E-Discoverry
  • Publishing
  • Workflow
  • Taxonomy
  • List Data

image

For Developing Managed and Silverlight

Based application using CSOM new set of assemblies have been added to SharePoint Root Bin Folder that you can access to use as proxy to write Client side code.  The methods in these assemblies use the same syntax that was used by 2010 Client OM Implement using ClientContext.  Now using Client OM you can add pages to a publishing site as well as traverse a Term Set and get or set status of your workflow. 

image

Let’s Create Couple of Examples.  There are so many possibilities when it comes to the new client OM.  So I just created small application to test some of the functionality.

image

Let’s check some basic SharePoint List Code.  In this Managed Client OM code I am connecting to my Web and adding a custom list then adding a Field using XML and then iterating to all the lists to display a message box. 

using(ClientContext context = new ClientContext(new Uri("http://intranet.contoso.com")))
{
Web RootWeb = context.Web;

ListCreationInformation newList = new ListCreationInformation();
newList.Title = "CSOM Custom List";
newList.Url = "Lists/CsomCustomList";
newList.QuickLaunchOption = QuickLaunchOptions.On;
newList.TemplateType = (int)ListTemplateType.GenericList;
List NewCustomList = RootWeb.Lists.Add(newList);


context.Load(NewCustomList);

string FieldAsXML = "<Field Name='ClientOMField' DisplayName='CustomField' Type='Text' Hidden='False' Description='Client OM Field' />";
Field fld = NewCustomList.Fields.AddFieldAsXml(FieldAsXML, true, AddFieldOptions.DefaultValue);

ListCollection allLists = RootWeb.Lists;
context.Load(allLists);

context.ExecuteQuery();
MessageBox.Show("List Created Successfully");
string strlist = "";
foreach(List aList in allLists)
{
strlist += aList.Title.ToString() + Environment.NewLine;
}

MessageBox.Show(strlist);

}

Now the below code will add a new item in this list.

using (ClientContext context = new ClientContext(new Uri("http://intranet.contoso.com")))
{
Web RootWeb = context.Web;

ListItemCreationInformation NewListItme = new ListItemCreationInformation();
List MyList = RootWeb.Lists.GetByTitle("CSOM Custom List");
ListItem MyItem = MyList.AddItem(NewListItme);
if (textBox1.Text.Length == 0)
{
MessageBox.Show("Please enter Title in Text Box to Save.");
return;
}

MyItem["Title"] = textBox1.Text;
MyItem["CustomField"] = textBox1.Text;
MyItem.Update();

context.Load(MyItem);
context.ExecuteQuery();
MessageBox.Show("Item Created Successfully with ID :" + MyItem.Id.ToString());
}

Here is an example of reading User Profile using CSOM.

using (ClientContext context = new ClientContext(new Uri("http://intranet.contoso.com")))
{
Microsoft.SharePoint.Client.UserProfiles.ProfileLoader loader = ProfileLoader.GetProfileLoader(context);

context.Load(loader);

UserProfile profile = loader.GetUserProfile();
context.Load(profile);
context.Load(profile.PersonalSite);
context.ExecuteQuery();

MessageBox.Show(profile.PersonalSite.Url);

}
Another Example of using Search Client OM.
using (ClientContext context = new ClientContext(new Uri("http://intranet.contoso.com/sites/Search/")))

   {

       context.Credentials = System.Net.CredentialCache.DefaultCredentials;

       KeywordQuery keywordQuery = new KeywordQuery(context);

       if (textBox1.Text.Length == 0)

       {

           MessageBox.Show("Please enter Title in Text Box to Save.");

           return;

       }

       keywordQuery.QueryText = textBox1.Text;

 

       SearchExecutor searchExec = new SearchExecutor(context);

       ClientResult<ResultTableCollection> Results = searchExec.ExecuteQuery(keywordQuery);

       context.ExecuteQuery();

 

       if (Results != null)

       {

           if (Results.Value[0].RowCount > 0)

           {

               DataTable dt = new DataTable();

 

               dt.Columns.Add("Title");

               dt.Columns.Add("Path");

               dt.Columns.Add("Write");

               dt.Columns.Add("Author");

               dt.Columns.Add("Rank");

 

               foreach (var Row in Results.Value[0].ResultRows)

               {

                   DataRow dr = dt.Rows.Add();

                   if (Row["Title"] != null)

                   {

                       dr[0] = Row["Title"].ToString();

                   }

                   else

                       dr[0] = Row["AccountName"].ToString();

 

                   dr[1] = Row["Path"].ToString();

                   dr[2] = Row["Write"].ToString();

                   dr[3] = Row["Author"].ToString();

                   dr[4] = Row["Rank"].ToString();

               }

 

 

               dataGridView1.DataSource = dt.DefaultView;

           }

           else

           {

               MessageBox.Show("No Results Found for your Query " + textBox1.Text);

           }

       }

       else

       {

           MessageBox.Show("No Results Found for your Query " + textBox1.Text);

       }

       

   }

Here is an example of adding Page to a Publishing Site using the Publishing Client OM.

 
if (textBox1.Text.Length == 0)

{

MessageBox.Show("Please Enter Page Title...");

this.textBox1.Focus();

return;

}

using (ClientContext context = new ClientContext(new Uri("http://intranet.contoso.com/sites/Pub")))

{

Web webSite = context.Web;

context.Load(webSite);

 

PublishingWeb web = PublishingWeb.GetPublishingWeb(context, webSite);

context.Load(web);

if (web != null)

{

    List PublishingLayouts = context.Site.RootWeb.Lists.GetByTitle("Master Page Gallery");

    ListItemCollection allItems = PublishingLayouts.GetItems(CamlQuery.CreateAllItemsQuery());

    ListItem Layout = allItems.GetById(35);

    context.Load(Layout);

 

    PublishingPageInformation PubPageInfo = new PublishingPageInformation();

    PubPageInfo.Name = textBox1.Text + DateTime.Now.Date.Hour + DateTime.Now.Date.Minute + ".aspx";

    PubPageInfo.PageLayoutListItem = Layout;

 

    PublishingPage page = web.AddPublishingPage(PubPageInfo);

    context.Load(page);

    context.ExecuteQuery();

    

    MessageBox.Show("Success....: ");

 

}

}

Now the same stuff can be done using REST and oData Interface.  I will explain this in another post.

Starting Silverlight Development with Samples


I was never a Silverlight Developer but after spending some time on SharePoint 2010 and watching the SL Dialogs all way around I decided to play with it for a moment. I never knew how SL Works. Just saw couple of vidoes and some SharePoint Sessions talks on Silverlight and SharePoint Integration that also shows SharePoint Client OM. So After spending some time on Hello Worlds I search on SL Toolkit and I am so happy that I found this link. When you see a running examples of the controls it is so easy to start development. The Link to the sample is given below. some of you are already experts so dont feel tough on me. I am just a begginer.

http://www.silverlight.net/content/samples/sl4/toolkitcontrolsamples/run/default.html

but I have completed web part that displays pending tasks to users which prooved quite handy in my situation as I was able to develop it in just 2 days. I will try to post the code soon.

I must say that Silverlight is simply “AWSOME”.

Client Object Model Basic Example – CAMLQuery


I was able to make a nice CAML Query Work in my Silverlight application so though it might be worth posting it over here as it might help some one. It is a query to read all items assigned to me or the group I am part of and the status is not completed. Now you can go ahead by your self and play with Query as you wish and make it to complex. But it is a working example.

void DoIt()
{
using (ClientContext ctx = ClientContext.Current)
{

string OrderBy = <OrderBy><FieldRef Name=’Created’ Ascending=’FALSE’/></OrderBy>;
                string Where = <View><Query><Where><And> +
                        <Or> +
                            <Membership Type=’CurrentUserGroups’> +
                                <FieldRef Name=’AssignedTo’/> +
                            </Membership> +
                            <Eq> +
                                <FieldRef Name=’AssignedTo’/> +
                                <Value Type=’Integer’> +
                                    <UserID/> +
                                </Value> +
                            </Eq> +
                        </Or> +
                        <Neq> +
                            <FieldRef Name=’Status’/> +
                            <Value Type=’Text’>Completed</Value> +
                        </Neq> +
                    </And></Where></Query> + OrderBy + </View>;

CamlQuery Query = new CamlQuery();
Query.ViewXml = Where;

TasksListItemCollection = ctx.Web.Lists.GetByTitle(“Tasks”).GetItems(Query);
ctx.Load(TasksListItemCollection);

ctx.ExecuteQueryAsync(Success, Fail);

};
}

void Success(object sender, ClientRequestSucceededEventArgs e)
{
this.Dispatcher.BeginInvoke(() =>
{
try
{
txtTaskCount.Text = TasksListItemCollection.Count.ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString() + ex.StackTrace);
}
finally
{

}
});
}

void Fail(object sender, ClientRequestFailedEventArgs e)
{
this.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(“Failed to Load Items ” + e.Exception.ToString());
});
}

Thanks to Thousands of Blogers who blogged about Silverlight and SharePoint Client Object Model.