Deep Dive into SharePoint 2013 and JavaScript – Part 2

Ahamed Fazil Buhari
 
Senior Developer
August 13, 2016
 
Rate this article
 
Views
7568

Hello everyone, this article is the continuation of my previous article (Deep Dive into SharePoint 2013 and JavaScript – Part 1). Here we will look into JSOM (JavaScript Object Model) in SharePoint.

JSOM

It was introduced in SharePoint 2010 as 1/3 of the new Client Side Object Model, CSOM. JSOM code is simply a JavaScript library that allows us to access SharePoint from client browsers. Like all JS libraries, JSOM is downloaded from the server to the browser on demand. JSOM has no authentication to execute the code, all code executes within the user context established by the browser.

JSOM is limited to current site collection.

clip_image002

Unless the cross-domain library is used, it cannot access different site collection.

From an architectural view, JSOM is made of JavaScript libraries. There are three libraries we’ll need in SP 2013 – MicrosoftAjax.js, Sp.runtime.js, SP.js all these are available via OOTB master page.

1. Batching:

It is all about performance, batching in JSOM reduces chattiness to improve performance. In the below simple example, before going into detail let’s look into the work of batching

 function doWork() {
   //Establishing the context - After the below line executes, we don't have context which      //to work - instead it is put into "batch"
     var currCtx = SP.ClientContext.get_current();
 // into "batch"
     var lists = currCtx.get_web().get_lists();
 //Not into "batch", this will execute immediately and it won’t wait for batch to be //processed
     alert("Im not in the batch");
 // into "batch"
     var myLists = lists.getByTitle("My List");
 // this executeQueryAsync doesn’t get added into the Batch, instead it cause the batch to send to the server for processing
     currCtx.executeQueryAsync(onSuccees, onFail);
 
     // more code
 }
 

clip_image004

All the JSON codes are queued up in the Batch and executeQueryAsync doesn’t get added into the Batch, instead it cause the batch to send to the server for processing. Any code coming after the executeQueryAsync will be processed immediately, it doesn’t wait for the batch result

As a part of executeQueryAsync call, there are two call back function one is for success and another one is for failure. While all this happening on the client the server receives the batch on the Client.svc REST endpoint, rips open the XML payload and begins processing it. All of the work is done by the regular Server Side Object Model interacting with the SharePoint db as required. If the server process the JSON with no unhandled exception then it will hit the onSuccees() function in the client side

clip_image005

This Batching process specifically applied only to JSON code, regular JavaScript code is not impacted by batching.

2. Client Context:

The next core concept on JSON is Client Context (SP.ClientContext). Client side code revolve around the client context. In JSOM, client context is our connection back to SharePoint. Everything begins here and everything revolves around context. One thing to be careful of is the name we use to represent client context shouldn’t be ctx, because ctx is SharePoint variable which we already seen its usage in Part -1 of this article.

3. Exceptional Handling:

Handling exception conditions is an important in any professional development effort. Unfortunately it’s one that far too often ignored in JavaScript. JavaScript natively support error handling through the same Try/Catch/Finally. This exceptional handling primarily reduces the round trip when dealing with batching and contacting the server.

 function sampleExceptionHandler() {
     var currCtx = SP.ClientContext;
     //Create instance of ExceptionHandling object and call startScope() method, indicate beginning of exceptional handling block
     _scope = new SP.ExceptionHandlingScope(currCtx);
     var_start = _scope.startScope();
 
     //Beginning of try block
     var _try = _scope.startTry();
     //attempt something that causes an error ("error list" not exists), code are inside //the try block now
     var lists = currCtx.get_web().get_lists();
     var errorList = lists.getByTitle("error list");
     //End of try block and dispose try object
     _try.dispose();
 
     var _catch = _scope.startCatch();
     //"Server side steps" to fix the error
     _catch.dispose();
 
     var _finally = _scope.startFinally();
     //**server-side actions that will always occur
     _finally.dispose();
 
     _start.dispose();
     currCtx.executeQueryAsync(onsampleExceptionHandlerSucceed, onFail);
     //last step to clean up and then call executeQueryAsync to commit the whole batch, //Try/Catch/Finally in all, up to the server to be processed.
 }
 
 

One thing we need to keep in mind when we are making use of this try catch blocks is that, this is our batch code inside this try block and it executes on the server. If we intermingle regular or non-JSOM code inside this block then it will execute immediately on the client regardless of whether or not an error actually happened.

This is how we do exceptional handling in JSOM to maintain the integrity of our batch and keep our application from being excessively chatty, even if something goes on.

Once the batch is processed in the server and send back to the client with success it doesn’t mean everything goes fine but still Success callback called. We use get_hasException function to check the hasException property of the scope, if that returns true, we know that error happened and was handled on the server as part of our batch.

function onsampleExceptionHandlerSucceed() {
var errTracker;
if (_scope.get_hasException()) {
errTracker = “Error on server was handled”;
errTracker += “\n\nError was ” + _scope.get_errorMessage();
}
else {
errTracker = “No error…”;
}
}

4. Reading Data using JSOM

We’ll start with a look at doing simple reads of information from SharePoint. As with Server OM mostly deals with webs, lists, listitems, files, and so on.

· Typical Process:

o Instantiate objects

 var currCtx = SP.ClientContext.get_current();
 myWeb = currCtx.get_web();
 lists = myWeb.get_lists();
 

o Load objects

currCtx.load(lists);

§ Trim properties requested – In this we can specify which property we want to filled up on the load statement. In the below line we’re loading web object, but just the ’Title’ and ‘ServerRelativeUrl’ properties.

currCtx.load(myWeb, ’Title’, ‘ServerRelativeUrl’);

//or Include can be used to fill up the property names

//currCtx.load(lists, ‘Include(Title,Id)’

o Commit Batch – Finally we need to commit our batch by calling – executeQueryAsync()

currCtx.executeQueryAsync(onSucceed, onFail);

o Work with properties in callback – once our batch has been committed and returned to our success callback we can begin to work with the object instantiated and the properties we asked to be filled up with their values. In the below alert statement you can see that we have used the properties which we were loaded earlier.

 function onSucceed() {
     alert("Website at " + myWeb.get_serverRelativeUrl() +
      "Title " + myWeb.get_title() + " has " + lists.get_count() + " lists.");
 }
 

· Properties

Properties must be requested before being referenced, if it is not then we’ll get a PropertyOrFieldNotInitilized Exception.

When we fill up an object via the load function it’s reasonable to expect that if we don’t limit properties that are filled up that they’re all going to be populated, but unfortunately it won’t work that way. Some properties are not filled up when we just call load without specifying which properties we want to populate.

· Scalar Properties

Only the Scalar properties are populated by default, Scalar properties are those that return – Bool, DateTime, String, Byte, Number, Char, Guid, Array of any of the above. Client Objects and Collections (Non scalar properties) should be explicitly requested.

· CAML Query

One of the most common approach for getting to one or more list items is the same approach we’d use in Server side code, a straightforward CamlQuery.

 var currCtx = SP.ClientContext.get_current();
 myWeb = currCtx.get_web();
 lists = myWeb.get_lists().getByTitle('TestList');
 var query = new SP.CamlQuery();
 query.set_viewXml("<View><Query><Where><Contains><FieldRef ..."+
                     +"..</Contains></Where></Query></View>");
 listItems = lists.getItems(query);
 currCtx.load(listItems);
 currCtx.executeQueryAsync(onSuccess, onFail);
 

5. Security in JSOM

One of the nice things about JSOM in SharePoint 2013 is the ability to interact with the security infrastructure of SharePoint. This is useful in managing security, setting permissions, managing users and groups, etc., the ability to check security asynchronously and present or update the UI accordingly is a huge capability. Here we start with simply security check using JSOM,

 function checkIfUserHasPermissions() {
 var currCtx = SP.ClientContext();
 myWeb = currCtx.get_web();
 //getting only the EffectiveBasePermission property from the web
 currCtx.load(web, 'EffectiveBasePermission');
 currCtx.executeQueryAsync(onSuccess, onFail)
 }
 
 function onSuccess() {
     //perms variables holds the SP Permission property value
     var perms = SP.PermissionKind.editListItems || SP.PermissionKind.fullMask;
 //get_effectiveBasePermission() function on web object which returns an SP.basePermissions obj that includes has() function
     if(web.get_effectiveBasePermission().has(perms)){
      alert("has permission");
     }
     else{
         alert("no permission");
     }
 }
 

While folder is a securable object in SharePoint, there’s no direct way to work with folder level permission in JSOM. Similar to the Server-Side object model, the way that we do will get the folder object as a list item. Once we have the list item that represents the folder, we can work with the permissions that way.

Security in Apps – Security programming and in fact, security in general is very different in apps when compared to regular SharePoint sites. The app security model is focused more on app and user specific permissions as opposed to groups. In an app web it is possible to add user permission directly or add new groups permissions, however it’s not possible to create or delete groups or add users to an existing group, which severely limits the possibilities for managing security in an app.

End of Part 2.

Happy Coding

Ahamed

Author Info

Ahamed Fazil Buhari
 
Senior Developer
 
Rate this article
 
Ahamed is a Senior Developer and he has very good experience in the field of Microsoft Technologies, especially SharePoint, Azure, M365, SPFx, .NET and client side scripting - JavaScript, TypeScript, ...read more
 

Leave a comment