Friday, March 14, 2014

Use JSOM from a plain webpage

With the richness of available javascript libraries (knockout.js, angular.js, …) combined with SharePoint JSOM, you can nowadays build some real nice functionality without need of server side code. Drawback however seemed that to be able to use JSOM, the script needs to be included on a SharePoint page. In some cases this is fine, when you utilize JSOM/Knockout/Angular to enrich a SharePoint page (sitepage, publishing page) with dynamic clientside behavior. But there are also scenarios that the clientside behavior is on its own (e.g. functionality exposed to the user via a dialog), and then it is undesired to include the SharePoint overhead: bloated HTML and an heaver page payload.
So the question is then, can you JSOM outside the context of a SharePoint page? Seems evident that it must be possible, after all it boils down to identifying the right resources to send to the browser, and that then does the work. However, it appeared to be a little less easy and logical to setup such a context. And the Microsoft provided information is insufficient and unclear.
After some trial-and-error, I now have it working. The required elements in the setup are the following:
  1. The page must be rendered by SharePoint; can be from the layouts directory (note: not as an application page), or from a SharePoint Document Library
  2. The page cannot be a plain .html; as it is required to utilize SharePoint server rendering pipeline
  3. Include a SharePoint.ScriptLink to deferred load 'sp.js'
  4. First trick: include '<SharePoint:FormDigest runat="server"></SharePoint:FormDigest>' in your page
  5. Second trick: encapsulate the javascript code that invokes JSOM, within a '<form runat="server"> -- </form>'. Especially this aspect took me some trial/discovery time.
With these 5 aspects applied, SharePoint JSOM can be used from a lean and lightweight webpage, without the SharePoint master page overhead.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">
<%@ Page Language="C#" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
  Assembly="Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<html dir="ltr" xmlns="">
<head runat="server">
  <meta name="WebPartPageExpansion" content="full" />
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Plain JSOM usage</title>
  <SharePoint:ScriptLink language="javascript" name="sp.js" OnDemand="false" runat="server" Localizable="false" LoadAfterUI="true"/>
  <SharePoint:FormDigest ID="FormDigest1" runat="server"></SharePoint:FormDigest>
  <form id="form1" runat="server">
     <script language="ecmascript" type="text/ecmascript">                                    
         $(document).ready(function () {
             EnsureScriptFunc("sp.js", "SP.ClientContext", function () {
                 var ctx = new SP.ClientContext();
                 var site = ctx.get_site();
                 ctx.load(site, 'Url');
                 ctx.executeQueryAsync(function (s, a) {
                     ko.applyBindings(new Demo.AppViewModel.ProcessesVM(site.get_url()), document.getElementById('DemoUsage'));

1 comment: