Exploring JavaScript Object Model Programming Paradigm In SharePoint

Introduction

 
Since SharePoint’s entry into the Content Management Field, developers had to interact with it using the server side object model. Though Out of the box web services were available it had its own limited development capability. With the introduction of client side object model things became much easier as developers could now interact with SharePoint remotely. Client side object model comes in 3 flavors,
  • .Net managed client side object model(CSOM)
  • JavaScript object model(JSOM)
  • Silverlight client side object model
.Net client side object model is used to access SharePoint remotely from a console application and provides strongly-typed representation of SharePoint objects using the client library Microsoft.SharePoint.Client.dll . JavaScript object model on the other hand is used to access and interact with SharePoint from within the client browser in an asynchronous fashion. We can make use of Content Editor Web part or SharePoint apps to directly communicate with SharePoint by making use of JSOM.JSOM particularly makes use of the SP.js library to handshake with SharePoint server. Silver light has become deprecated and so is Silverlight Client Object Model. 
 

JSOM Working

 
Just like any other API JSOM is dependent on 3 main client side libraries. These are referenced via SharePoint Master Pages. However if we are using a non-SharePoint custom master page ensure we have the references to the below libraries,
  • MicrosoftAjax.js- Usually loaded by ScriptResource.axd
  • SP.Runtime.js- Loaded from the LAYOUTS folder
  • SP.JS- Loaded from the LAYOUTS folder
In order to perform an operation using JSOM, the request goes from the client browser to the REST service named client.svc residing in the SharePoint Server. This is an asynchronous call as after the request has been made, the code will continue to run. When the request returns one of the success/failure call back methods that are registered will be called to take care of the returned data.
 
data
 
Client.svc service is the WCF service that is responsible for performing all of the operations requested by JSOM. The service is located at /_vti_bin/client.svc on the SharePoint Server. The WCF service endpoint appends /_vti_bin/client.svc/ProcessQuery to process the request that is coming from the client browser and requires a formatted Xml Request as per the protocol specifications. So the request coming from the client browser will xml formatted and the return type will be a JSON response.
 

Script on Demand

 
JavaScript object model extensively makes use of script on demand framework (SP.SOD). It means that the script won’t be loaded until explicitly requested. Starting from SharePoint 2010 the scripts will be loaded on to the page only as required. Multiple methods are available in SP.SOD framework to implement On Demand scripting. We will look into two main commonly used functions which are utilized extensively in JSOM implementations.
 

SP.SOD.executeOrDelayUntilScriptLoaded

 
SP.SOD.executeOrDelayUntilScriptLoaded(functionName, scriptFileName) schedules an asynchronous callback function (functionName) which will be called when the script(scriptFileName) has finished loading to the page. This method ideally delays the execution of the JSOM code until the dependent scripts has been loaded. SP.js is the primary resource file required for JSOM. If the JSOM code executes prior to the loading of SP.jS library we will get object reference errors. So to make sure JSOM is executed after SP.js is loaded on to the page we make use of ‘SP.SOD.executeOrDelayUntilScriptLoaded’ as :
 
Usage
  1. SP.SOD.executeOrDelayUntilScriptLoaded(getWeb, 'SP.js');    
  2.     
  3. function getWeb() {     
  4.     
  5. // Get the current client context and Web instance.    
  6. var clientContext = new SP.ClientContext.get_current();    
  7. var oWeb = clientContext.get_web();    
  8. }   
One of the limitations of SP.SOD.executeOrDelayUntilScriptLoaded is that if the script file is not loaded, the JSOM code block that is waiting to be executed will wait endlessly and may not even be executed at all. In order to circumvent this issue SP.SOD has another useful function SP.SOD.executeFunc.
 

SP.SOD.executeFunc

 
ExecuteFunc method call provides the flexibility to call an On Demand Script and then run another function once the script has finished loading. It resolves the drawback with ‘ExecuteorDelayUntillScriptLoaded(It cannot trigger an On Demand Script).
 
Usage
 
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', retrieveListItems);
 
ExecuteFunc method takes three parameters,
  • Sp.js- the script file that will be invoked and loaded to the page. It can be any file
  • SP.ClientContext- The main object within the script file that will be used. It can be kept null.
  • retrieveListItems- The function to run after the script files are loaded to the page.
JSOM Structure
  1. $(document).ready(function() {    
  2.     SP.SOD.executeFunc('sp.js''SP.ClientContext', retrieveListItems);    
  3. });    
  4. var collListItem;    
  5.     
  6. function retrieveListItems() {    
  7.     //Get client context,web and Listobject    
  8.     var clientContext = new SP.ClientContext();    
  9.     var oWeb = clientContext.get_web();    
  10.     var oList = oWeb.get_lists().getByTitle('Employees');    
  11.     //Get list item collection    
  12.     collListItem = oList.getItems(SP.CamlQuery.createAllItemsQuery());    
  13.     //Load the client context and execute the batch    
  14.     clientContext.load(collListItem);    
  15.     clientContext.executeQueryAsync(QuerySuccess, QueryFailure);    
  16. }    
  17.     
  18. function QuerySuccess() {    
  19.     //Create enumerator object and loop through the collection    
  20.     var listItemEnumerator = collListItem.getEnumerator();    
  21.     while (listItemEnumerator.moveNext()) {    
  22.         var oListItem = listItemEnumerator.get_current().get_item('Name');    
  23.         console.log("Name : " + oListItem);    
  24.     }    
  25. }    
  26.     
  27. function QueryFailure() {    
  28.     console.log('Request failed' + args.get_message());    
  29. }   
  1. As a first step, get the current context by calling SP.ClientContext.get_Current method. Since JSOM is running in the context of the browser we cannot impersonate the user . Only way to change the user context is to run the client browser in the required user’s credential.
     
  2. Once the context object is created, make a call to get the current web
     
    var oWeb = clientContext.get_web();
     
  3. The get_lists() method of the web object returns all the list collection present in the current web. Applying getByTitle () on the list collection fetches the specific Employees list.
     
    var oList = oWeb.get_lists().getByTitle('Employees');
     
  4. Now, call getItems method on the list object to return all the items
     
    collListItem = oList.getItems(SP.CamlQuery.createAllItemsQuery());
     
  5. The context object provides the load method which is responsible for loading objects and collections from the server. Whatever object is passed into the load method is populated and can be used in the subsequent call back function.
     
  6. If you want to work with the child properties of an object, it must be loaded by calling ‘clientcontext.load(object)’ followed by the executequeryasync call .Otherwise, you will generate an exception such as the following,
     
    “The property or field has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.”
     
  7. JSOM provides the flexibility to execute the requests in batches. Thus each request to create a web object, create a list from the web object won’t be send as separate requests to the server. Instead all the requests will be batched together and send to client.svc upon calling the executequeryasync call. In the above example, we are making calls on the context, web, and list objects but cannot work with the objects’ child properties. Only when the call to ExecuteQueryAsync method is made, an XML request is generated and then sent to the server’s client.svc for processing. As part of ExecuteQueryAsync you have to provide two callback – a success and failure call back. These methods specify how to proceed when the request is processed.
     
  8. Depending on the Success/ Failure of the executeQueryAsync call, control will be passed to the appropriate call back function. From within the function we can then access properties of the loaded object. For instance in the above example, the loaded object is the list item collection which can be iterated by instantiating an enumerator object as shown below,
    1. var listItemEnumerator = collListItem.getEnumerator();    
    2. while (listItemEnumerator.moveNext()) {    
    3. var oListItem = listItemEnumerator.get_current().get_item('Name');    
    4. console.log("Name : " + oListItem );    
    5. }   
JavaScript object model is an asynchronous programming model that enables communication with SharePoint in the client side. As with any programming constructs JavaScript object model also has exception handling techniques. JavaScript provides native try/catch to handle exceptions. Though JSOM is based on JavaScript using Try/Catch will not really do exception handling in JSOM. This is because of the asynchronous nature of JSOM. In JSOM all the operations are send as a batch to ‘client.svc’ WCF service in the server that would process the request.
 

Exception Handling

 
SharePoint however provides an exception handling mechanism similar to JavaScript try/catch of the format startTry() and startCatch() . Its implementation is similar to try/catch.
 
The main object that handles the exception in JSOM Is called ‘ExceptionHandlingScope’.It provides the below methods to perform exception handling.
  • startScope
  • startTry
  • startCatch
  • startFinally
Let’s see how it works,
 

Internal Implementation

 
As with any JSOM implementation we create the starting object which is client context. After that we create an exception handling scope object using the client context. Once the exception handling scope object is created we call its startScope method. This method indicates that the entire code within the block will be eligible for exception handling.
 
code
 
Once the exception handling scope starts we can initiate the try block using the startTry method. Any code written within the startTry method will be checked for exceptions and in the event of an exception the control will be passed to the exception handling block which is the catch block. The code block that began with startTry will be ended using the dispose method. The exception handling block that will be called in case of any error in the try block is the catch block which is instantiated using startCatch method. Within this block we can add the code that will resolve the issue that happened in the try block. Similar to try block catch block will also be ended using the dispose method.
 
The last code block of the exception handling paradigm is the finally block which is instantiated using the startFinally () method. This block will have all the code that needs to be run regardless of if an error occurs. The dispose method can be called to indicate the end of the finally block.
 
We can see how exception handling paradigm can be used in a real word scenario. Let’s say, we are trying to update a list which does not exist in SharePoint environment. This will ideally throw an exception as the object is not present. We will write the erroneous list update code in try block and handle the exception in the catch block by creating the list. In the finally block we will again try to update the list. This time the list will be updated without any exceptions.
 
Full Script
 
The full code for implementing exception handling is shown below,
  1. <script language="javascript" type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>    
  2. <script language="javascript" type="text/javascript">    
  3.     $(document).ready(function() {    
  4.         SP.SOD.executeOrDelayUntilScriptLoaded(CheckandCreateList, "sp.js");    
  5.     });    
  6.     
  7.     function CheckandCreateList() {    
  8.         //Get the client context and web object     
  9.         var clientContext = new SP.ClientContext.get_current();    
  10.         var oWeb = clientContext.get_web();    
  11.         //Create exception handling scope and start the scope     
  12.         var exceptionScope = new SP.ExceptionHandlingScope(clientContext);    
  13.         var startScope = exceptionScope.startScope();    
  14.         //Instantiate Try Scope     
  15.         var tryScope = exceptionScope.startTry();    
  16.         //Add the code to update the list that does not exist which will cause error.     
  17.         var oList = clientContext.get_web().get_lists().getByTitle("ExceptionList");    
  18.         oList.set_description("Updated Description");    
  19.         oList.update();    
  20.         //Dispose the scope     
  21.         tryScope.dispose();    
  22.         //Instantiate Catch Scope     
  23.         var catchScope = exceptionScope.startCatch();    
  24.         //Within the catch scope write the JSOM code to create new list which will resolve the error.     
  25.         var newListCreationInfo = new SP.ListCreationInformation();    
  26.         newListCreationInfo.set_title("ExceptionList");    
  27.         newListCreationInfo.set_description("Catch Updated Description");    
  28.         newListCreationInfo.set_templateType(SP.ListTemplateType.genericList);    
  29.         clientContext.get_web().get_lists().add(newListCreationInfo);    
  30.         //Dispose the Catch Scope     
  31.         catchScope.dispose();    
  32.         //Instantiate the Finally Scope     
  33.         var finallyScope = exceptionScope.startFinally();    
  34.         //Update the newly created List     
  35.         var oList = clientContext.get_web().get_lists().getByTitle("ExceptionList");    
  36.         oList.set_description("Finally Updated Description");    
  37.         oList.update();    
  38.         //Dispose finallyScope     
  39.         finallyScope.dispose();    
  40.         // Dispose startScope     
  41.         startScope.dispose();    
  42.         //Execute the batch     
  43.         clientContext.executeQueryAsync(Success, Failure);    
  44.     }    
  45.     
  46.     function Success() {    
  47.         console.log("The list has been created successfully.");    
  48.     }    
  49.     
  50.     function Failure(sender, args) {    
  51.         console.log('Request failed - ' + args.get_message());    
  52.     }    
  53. </script>   
Output
 
Console Output,
 
Output
 
Output
 

Summary

 
Thus we saw the basics of JavaScript Object Model implementation and exception handling in SharePoint.