Thursday 5 January 2017

Changes to Custom Actions and handling of JavaScript in SharePoint Online

Recently our Custom Actions stopped working in modern document libraries in Office 365. We were surprised at this, because as far as we were aware we weren’t doing anything that went against “new” guidance for working with modern team sites and modern document libraries. Since the beginning of modern doc libs, Custom Actions which use ScriptSrc or ScriptBlock have not been supported (same with JSLink customizations). But we weren’t doing any of these things – our specific details were:

  • A Custom Action using a URL-based action which opened a modal dialog (pop-up) – in our case, to show a custom options page to the user
  • Use of “EditControlBlock” as the location, so our menu item appears on the context menu for each document
  • Registered on our “base document” content type which is used in our document libraries

And for a while everything was great - as expected, our menu item showed up in both the classic and modern document library experience. However, in early December (2016) our menu item disappeared from the modern experience, across all our tenancies (eventually). These images show our menu item (named “Actions”) visible in the classic view but not modern:





New rules for Custom Actions

Essentially, Microsoft have made changes in exactly what is supported with Custom Actions. I guess you could say this doesn’t align 100% with previous guidance on the topic – or at least, some low-level details were ambiguous or open to interpretation. For example, the Update on Modern Document Libraries and Extensibility blog post says this:

“We’ve already made some good progress here.  Theming, global navigation links, and URL-based custom actions that extend the ribbon and context menus are already supported in the modern document library experience.  This ensures that customers and partners taking advantage of these features can use the modern document library experience without compromising their customizations.”

For our part, we figured that we should be fine because we’re using a URL (rather than ScriptSrc or ScriptBlock). However, talking with the Office 365 engineering team, it became clear that a URL which contains JavaScript (e.g. Url=’javascript:OpenDialog()’) is no longer permitted – although this did work until early December. Additionally, targeting by content type no longer works – the only option currently is to target by list template type, for example:

  • 100 – custom list
  • 101 – document library
  • ..and so on

UPDATE – targeting by content type now works again. So you can once again target by content type or list template type..

I appreciated the help from folks in the product group who helped me understand what their code is currently doing, and where things might head in the future – thanks guys.

Anyway, we had to make some changes. In our case, since we can no longer open a dialog from the menu (since that requires some JavaScript), we’re changing our experience to navigate the user to a full page instead. Also, we need to change the targeting from content type to list template type – that’s mainly OK, but in truth does give us a slightly different scope to what we really wanted.

Could any of these changes affect you? If so, you’ve probably noticed already – but either way, it’s definitely worth SharePoint developers becoming clear on the latest developments in this space. Overall, there is a longer list of these kind of things which are no longer supported on modern lists and libraries, including:

  • Custom master pages
  • JSLink (field and view types)
  • AlternateCssUrl
  • Custom Actions which use ScriptLink to add JavaScript to the page

On the bright side, there is now some official documentation in the form of MSDN articles which provide more detail than I’m including here. I highly recommend going through these:

Using the classic experience as a workaround

Remember of course that these changes don’t affect the classic experience. You have the choice of continuing to use that (e.g. by setting it at the tenant level) if you’re happy with that. We weren’t unfortunately, because we want our uses to have the benefits of the new document library UX (better mobile experience, improved metadata editing, new summary panel, sorting/filtering enhancements and so on).

Looking to the future (especially around JavaScript in Office 365)

Microsoft have noted in several places that new mechanisms will come to SharePoint Online to match many of the previous capabilities. They may not take exactly the same form as the previous mechanisms, but it should be possible to achieve the same overall result. These include:

  • Custom master pages --> some other “deep branding” controls (which may or may not provide the ability to control the full HTML)
  • JSLink --> some other mechanisms to control the rendering of list views and fields
  • CustomAction + ScriptLink --> some other mechanism to add JavaScript to pages

Thinking specifically about JavaScript, I think it’s clear that there will be increased controls around administrator approval of scripts – the idea is to provide more governance so that arbitrary scripts cannot be added by a developer without wider approval. After all, that’s why Microsoft have made some of the recent changes to pull back on previously supported approaches – they did leave holes which could result in trouble for some organizations. Despite the occasional pain on the journey, I think we all need to accept that these changes are for the better and the resulting position should be better overall.


sympmarc said...

While I certainly understand the need for governance, my fear is that more constraints will simply mean less productivity in large organizations that don't do governance well. If we're forced to get some sort of admin approval for every piece of JavaScript, many of the powerful customizations will simply not happen. Requiring all changes to go through the choke hold of IT may well be the death knell for the platform, as people turn to other solutions which provide them the capabilities they need.


Chris O'Brien said...


BUT, you can't get away from the fact that JavaScript running in the context of the user can do dangerous things (e.g. send sensitive data away to a malicious service). It's all a difficult balancing act!


Krunal Patel said...

we had same issue and contacted MS Support and after 10 days of consultation with product team they comeback with info, it is architecture change and will have new way to support customisation sometime in first quarter of 2017.

William van Strien said...

Hi Chris,
Thanks for sharing this experiences. I agree strongly with Marc: a strong aspect of SharePoint (whether on-prem or online) is that power users are enabled to build business solutions as modern, clientside apps; without need to go via IT. Introducing an hurdle via IT approved scripts will diminish that power, and make business users look to other platforms that don't unnecesserality block the business progress (e.g, with the Lightning platform).
Also countering your argument why governance is needed to prevent misuse: this governance on SPO-online deployed scripting does not prevent that, one can consume via CSOM and SharePoint services still the SharePoint data/documents from script deployed outside SharePoint This what Microsoft positions as a strong development argument of the platform since 2013: extend SharePoint by external applications (E.g. Provider-hosted AddIns). In all clientside-based cases, the (sensitive) access is restricted to what the current user is allowed to access. Via clientside scripting, you cannot bypass the SharePoint permissions. The permissions are the correct governance level to prevent unauthorized data usage and sharing.

Regards, William.

Unknown said...

Hey Chris,

I just ran into the issue of trying to create a Sharepoint Hosted Add-In and use Javascript CSOM with the Cross Domain Library to create a Custom Action on the top level Site to inject javascript to start to brand a client's Sharepoint site. I kept receiving the "Access Denied" error even though I checked and re-checked that I was using the CDL correctly and asking for the correct permissions in my AppManifest. I finally found the solution after a few hours and found the help from StackOverflow. It was the site admin setting of "Prevent users from running custom script on self service created sites" from what I read. It can take up to 24 hours for the setting to change if changed in the admin part so I found that you can use PowerShell to set DenyAddAndCustomizePages to 0 from the help of c-sharpcorner here

I changed the setting and was able to add the custom action with the ScriptLink with the help of the Sharepoint PnP from github here. Now all is well and my pages are getting the javascript injection!

I wanted to share this in case it helps you or someone else coming across this article.

Thanks for your great articles!