Monday, 8 September 2014

JavaScript-based provisioning in SharePoint/Office 365

In this post I want to specifically focus on the idea of JavaScript-based provisioning code – a potentially useful approach which has a place in every modern SharePoint developer’s toolkit. This is the idea of using SharePoint’s JSOM API (i.e. the JavaScript version of CSOM) to perform various one-time configuration steps for SharePoint sites - I was initially somewhat sceptical of this technique (JavaScript? For provisioning? Would that be reliable??), but having seen some team-mates use it with success on projects (kudos guys!), I think it’s worthy of consideration.

Background

For SharePoint developers who are working with SharePoint Online/Office 365, or are working on-premises but choosing not to use full-trust WSPs simply to ensure their solution is “cloud-friendly”, the previous options for custom SharePoint code are no longer available. And some common scenarios still require code – especially when some form of custom site template is being developed, or we are working towards automated configuration of sites.

Some examples of provisioning steps that a developer might need to use code for could be:

  • Binding Managed Metadata/taxonomy fields
  • Setting a theme/Composed Look on a site
  • Setting the master page of a site
  • Modifying navigation settings
  • Branding OneDrive (personal) sites
  • [Optional] Provisioning fields and content types through code, rather than XML

This presents a challenge when server-side SharePoint code cannot be used. As we all know, Microsoft have deprecated the use of sandboxed SharePoint code (which we might previously have used for say, a Feature receiver), and this facility may be turned off in Office 365 in in the future. So, we have to use one of the remote APIs instead – and the code will either run from some other server (e.g. the .NET CSOM) or the user’s browser (JSOM).

Options for remote code

Broadly, the options for remote code include:

  1. Some use of the .NET CSOM API:
    1. Code deployed to a cloud service such as Azure, or running off your own server somewhere. This could be an “App for SharePoint”, or it could just be remote code which does not use app authentication.
    2. A “PowerShell + CSOM” script you wrote
  2. Some use of the JSOM API (i.e. the JavaScript version of CSOM)
  3. Some use of the REST API (either from JavaScript or remote server-side code)

As Microsoft put it, your custom code either needs to move UP to the cloud or DOWN to the user’s browser.

The JavaScript-based (JSOM) option

The idea of using JSOM code for site provisioning steps is a strange one initially. What happens if the user closes their browser as the code is running? Will the site get configured properly? What about if the user is very far away from the server on a slow connection? It was questions like these that made me sceptical initially, but with some safeguards and caveats in place I think it’s an interesting option for remote code. I’ll talk about how it works in a second, but first here’s why I think it’s interesting:

Side-stepping the “server-side remote code” issue

As a modern SharePoint developer, I’m all onboard with apps and remote code. In several cases I’ve implemented remote SharePoint code in Azure (e.g. see my Deploying SP2013 provider-hosted apps/Remote Event Receivers to Azure Websites (for Office 365 apps) post). So yep, I’m cool with that stuff! And I’m also down with kids in terms of Microsoft’s OfficeDev Patterns and Practices samples, which cover a ton of scenarios such as those I list above – they’ve effectively written a great wrapper around the .NET CSOM API calls, which make it really easy to get these tasks done.

BUT THIS TYPE OF CODE STILL HAS TO BE DEPLOYED SOMEWHERE! On-premises servers (e.g. some IIS boxes) can bring complexity in terms of high-availability, access outside the firewall, SSL certificates, backup and restore, and so on. Of course, cloud options exist too. If you (or your client) is already using Azure, then GREAT! It’s really not too difficult to get the code deployed and running there, and Microsoft take care of the operational/I.T. Pro factors listed above. But in many of the organizations I’ve worked with, unfortunately Azure (or similar cloud service) is not yet embedded in the I.T. department’s toolkit. There is no Azure subscription, with someone in I.T. already paying the monthly invoice. And there are all sorts of operational I.T. topics to discuss and get agreement on before we could get to that position – who owns responsibility, what kind of data will we be storing there, who has access, how does it fit with any existing SLAs/OLAs, which department/cost centre pays the bill and so on.

Interestingly, working in an “implementation partner” as my team does, we almost have an option of deploying some remote code for a client to Azure and not needing to involve them in this decision. The Azure Websites offering has a free option, and therefore all the billing questions/set-up could be avoided. However, you do not get high availability in free mode – so if the machines your code is running on are being patched, you’ll have downtime. So in the end, unless your code is trivial this probably isn’t an option.

Consequently, the idea of implementing remote code in JavaScript can be quite appealing in some cases.

A robust implementation for JavaScript-based provisioning

So, we’d need some way of making a JavaScript-based approach somewhat reliable. The pattern my guys have used is this:

  • The SharePoint site is created (perhaps from a custom WebTemplate which takes care of some settings in XML) – at this point, the site is NOT fully configured
  • A custom JavaScript file is referenced on every page – this checks to see if set-up steps have been completed yet. If not, the user’s permissions are checked to see if they are a Site Owner and whether we can proceed (with a “A site owner needs to visit this site to configure it” message shown if not).
  • When a user hits the site, our code runs. If we can proceed with set-up, a dialog is shown - “Please wait – we are getting your site ready”
  • The code starts to execute provisioning steps – perhaps setting a Composed Look and/or custom master page, binding taxonomy fields and so on
    • When each step completes, an entry is written to the web property bag e.g. “BrandingApplied = true”
  • When all steps are complete, a success message is shown and the “getting your site ready” dialog is automatically closed. The site is now ready for use.

As you can guess, it’s only when all confirmations are written to the property bag that we no longer attempt to run the steps. This works surprisingly well in practice – users/site owners are comfortable seeing these kind of messages, and having a site owner hit the site initially tends to work out fine, since they are the site creator. If any failures occur, well that’s fine too because the uncompleted steps will be re-tried on the next page load.

To illustrate the experience, here’s what the site owner might see during configuration (shown here on a test page, rather than a “real” site home page):

Dialog large

Of course, you could do something a bit fancier in terms of look and feel.

Some sample code for JavaScript-based provisioning

In my other article Three cloud-friendly ways for developers to provision Managed Metadata fields in SharePoint/Office 365, I show some JavaScript code which does the basics described above – specifically for binding taxonomy fields to MM Term Sets. This is the same sample as in the other article - I’ve included it again below for convenience, but I recommend reading the other article too as it has some extra notes about how the code should be used (like the fact you might want to enhance with JavaScript promises). Note that it doesn’t deal with setting confirmations in the web property bag, but it would be fairly simple to add this. The code will work with Office 365 or on-premises SharePoint:

I guess the main thing to take from this code is the approach - showing the dialog whilst several steps of JSOM code are being executed. In this simple example, when the code completes our taxonomy field will be bound and ready for use – but in our real-life projects obviously many more steps are performed.

Summary

Whilst the idea of using JavaScript/JSOM code for provisioning can seem strange, I believe it has it’s place and can be the right choice sometimes. Certainly, if you have no other need for remote code and/or do not have a hosting location (such as Azure or on-premises IIS servers) ready to go in a production sense, then the JSOM approach does offer you a way of running remote SharePoint code without the hassles that come with the alternatives. As always, consider the trade-offs and think about what’s right for you – but hopefully the information here helps you along the way.

6 comments:

Fran Rodriguez said...

I think this is a great and simple approach for init'ing sites.

We use it with a slight variation: A "MySiteTemplate Configuration" feature activated by default in the site template, which deploys a
<CustomAction ScriptBlock="MyNamespace.MySiteTemplate.Init()" ... />
The last step in the javascript code is to deactivate its own feature, so in the future no more "Is this site configured?" checks are performed.

Chris O'Brien said...

@Fran,

Thanks for adding this - useful info that might help folks "production-ize" this approach.

P.S Always good to know my team-mates are reading my articles :)

Tal said...

Hi Chris,

Long time reader first time replyer ( am moving up the SharePoint dev chain so am now at a level where I feel I can actually contribute to these discussions!).

Thank you for writing this article as I think JavaScript provisioning of elements is seen as "dirty" or "hacky", but I agree it really can be done cleanly, and articles from trusted sources like yourself help people trust the process.

I wanted to comment on your approach though, as you have discussed using templates. I have developed a site provisioning approach but since this was for a publishing site I could not use templates. We also have a new requirement to configure MySites which is even more tricky. I may write a post myself on this...

For our publishing site we did not want to change the user experience for creating sites, so what I did was write a function that runs on every page. If it found that the current URL was "viewlsts.aspx" it would create a new button next to the "new subsite" button. This button would point to the same "newsubweb.aspx" page but add a query string. Another function that runs on all pages checks for the existence of the query string and if so, slightly modifies the user experience so that they have the same look and feel, but are unable to choose the template or set permissions options. When the user hits "Create" a dialog pops up and tells them their site is being created, and all provisioning and config is done client side. The solution to "what if the user leaves the page" is firstly a confirm box that warns the user, but secondly all activities are logged to a list in the root site which tracks site creation requests, time to create the site, and logs any errors that occurred.

I think I might write a post on this, and also about my experience with configuring mysites... happy to send you a link to these when they are written if you are interested.

Tal

Chris O'Brien said...

@Tal,

Sounds like a nice approach. Good stuff, you should blog it :)

Chris.

Mark Wilson said...

So you would recommend this over sandbox even for on-prem? It feels to me that provisioning files from an app web to a host web via JSOM seems a little heath-Robinson if you see what I mean. Looking at Jeremy Thake's blog the sandbox isn't going to actually get turned off for some time.

Also I'd be interested in knowing how you tackle automated builds with JSOM provisioning. Once you have installed the app via side loading then you need to visit the app page to execute the JavaScript. This may well need to occur early on in an automated deployment for essential things like content types. It feels rather fragile to start spinning up browsers as part of a build process..

Chris O'Brien said...

@Mark,

I'm not sure I'd use this approach for provisioning files - I'm thinking more about provisioning steps which really need code. That said, the Product Group are starting to encourage implementers to move away from nearly all aspects of declarative provisioning if you want the optimum in cloud-friendliness *and* upgradability of your solution. My personal view, however, is that at the moment this comes with some trade-offs (especially in Office 365) in scenarios where you need high levels of control of updates (e.g. publishing intranet). Probably a deeper topic for another article though.

In terms of sandbox use, I'd definitely avoid *code* in the sandbox - the guidance is now clear on that. If you're on-premises, yes you do have more control (i.e. don't disable it if you're using it!) compared to Office 365, but clearly you aren't really achieving "cloud-friendly" if your solution cannot be taken to the cloud (i.e. Office 365 with no sandbox code allowed) without major re-engineering.

And for automated builds, yes I agree that JSOM-based provisioning brings a challenge here. On the flip side, I don't really see anything too bad about spinning up browsers in a build process - if that's the implementation pattern you're using, then actually having automated tests around it would be exactly what you would want. After all, if the build process was doing something different to the production provisioning process, then you're not testing what's needed and would have a gap.

As always, lots to consider :)

Cheers,

COB.