Wednesday, June 29, 2016

SharePoint Hosted Add-In or Plain Old JavaScript / HTML5 / CSS?

When Microsoft released the SharePoint App-model (meanwhile renamed to Add-In model), it almost instantaneously became the preferred and dominant development approach for SharePoint customization. Now several years later, and the hype is gone, the question arises whether the Add-In model is the right answer for all SharePoint customization scenarios.
I dare to say no. And feel myself strengthened in that opinion by Microsoft’s latest and greatest SharePoint development approach: the SharePoint Framework. Yes, the Add-In model brings a lot of value, but at the expense of additional development, maintenance and runtime (performance) costs. In case you can bring the same functional value via a strict JavaScript + HTML5 + CSS setup, you can avoid these additional costs. Simple deploy the functionality via resource files, upload to a document library, and include them in the runtime SharePoint page context via a ScriptEditor. Much simpler to develop and deploy than a SharePoint hosted Add-In. And not hindered by iFrame boundaries.
Does this mean I see no value at all for the SharePoint-hosted Add-In model? No, there are definitely scenarios. A clear one is that of a software vendor: with an Add-In the vendor has a self-contained package that buyers can install in their SharePoint site. Another example is for a piece of functionality that is reused throughout the site structure, and that needs per usage its own storage in SharePoint. The Add-In model can provision this per Add-In installation in either the hostweb or the appweb.

Wednesday, June 8, 2016

Preserve code blocks ('xd:preserve') not supported in InfoPath Forms Services

See Readonly display of MultiLookup value in InfoPath Forms Services: my initial approach was to handle this in the InfoPath template itself, via Custom XSLT:
That approach works when testing in InfoPath Designer - preview.
However, upon publishing the template to SharePoint my custom XSLT is lost. Microsoft in MSDN article Using Custom XSLT in InfoPath Form Templates states that you can protect your XSLT customization for overwriting via 'xd:preserve'. Indeed with that inserted, upon saving the template the customizations are preserved:
However, I ran into another issue that Microsoft does not make clear in the referred MSDN article: forms with preserve code blocks in it cannot be published to SharePoint.
Hidden in other MSDN article Creating InfoPath Form Templates That Work With InfoPath Forms Services it states that 'XSLT extensibility (xd:preserve blocks)' are amongst the 'Features with No Direct Parallel on the InfoPath Forms Services'.
Note that you can [still] apply Custom XSLT in InfoPath Forms Services context, the limitation is that code preservation is not supported. So on every save in InfoPath Designer, the custom XSLT code blocks get overwritten, and you would have to insert them again. That effectively makes this InfoPath customization approach [at least for me] unmanageable and unworkable for sustainable utilization in InfoPath Forms Services context. Therefore my design decision to implement the required behavior 'outside' InfoPath Forms Services, via a clientscript approach.

Readonly display of MultiLookup value in InfoPath Forms Services

Business question:

Have an InfoPath form that on one tab allows submitter to select zero to more impacted IT applications, and on another tab (for other business role) display this selection readonly.

InfoPath / IT answer:

  • Have multiple Views in the InfoPath form / template;
  • On the 'input' View, include a Multiple Selection List (MultiSelectList) control, and bind to the MultiLookup List Column (or ContentType Field);
  • On the 'display' View, visualize the current value of MultiLookup via a Repeating Table control. Via InfoPath configuration (control properties) remove the option for user to include new entries in the table: This part takes care of displaying [only] the selected value(s);
  • What then remains is to make the control readonly, to prevent that the MultiLookup value can be changed on this tab. InfoPath does not itself support to disable the Repeating Table control. However, you can achieve this for InfoPath Forms Services context via (the power of) javascript: include on 'editifs.aspx' page script with a method that sets the html control to disabled. A complexity here is that IFS loads the form asynchronously after the surrounding page is loaded in browser, and that no event is triggered to notify the form is loaded. To handle that, I've programmed a polling approach that recurring checks whether the resulting HTML table is now present in DOM, and then disable it:
    var InfoPathCheck; var maxNrChecks = 10; $(document).ready(function(){ InfoPathCheck = setInterval(function() { //Wait for InfoPath to finish loading HasInfoPathLoaded(); }, 200); }); function HasInfoPathLoaded() { var selectAppl = $("#ctl00_m_g_d1ea83c5_3306_41e4_8419_01cfcf73921e_FormControl0_V1_I1_R5"); if (selectAppl.length > 0 || --maxNrChecks === 0) { clearInterval(InfoPathCheck); if (selectAppl.length > 0) { $(selectAppl).prop('disabled', 'disabled'); } } }

SharePoint mobile app + SharePoint Framework support?

The latest development approach for SharePoint customizations is via the new SharePoint Framework. MVP Waldek Mastykarz has multiple informative posts on what it is and how to utilize. In Everything you need to know about the SharePoint Framework he makes a remarkable statement: "When building solutions on the SharePoint Framework, if you follow the guidelines provided by Microsoft, not only will your solution look great on mobile devices but it will also be rendered in the native SharePoint mobile app which will be released shortly".
Remarkable, as I'm confused by how a native App could be running clientscript. So I challenged Waldek and Bill Baer via twitter to expand on that:
Well, turns out the statement is for now a bit too early. Microsoft is working on bringing this capability in the new SharePoint mobile app, and Vesa Juvonen acknowledges that Microsoft should tackle my question in their message.
UPDATE (June 13) Jeff Teper, interviewed at SharePoint Saturday Paris, answered on my question, being "We host html in JavaScript" [within the native code of the mobile app]. Although this is merely the high-over answer, and I want to understand more of the lower level details; this is sufficient for now. Details will be shared later by Microsoft and informed MVPs.

Wednesday, June 1, 2016

Performance repercussions of the Add-In model

The Add-In model is great to deliver self-contained functionalities, isolated from (harming) the SharePoint farm health - runtime and wrt physical installation. But be aware that there is a price: performance. In general, the overall performance will be negatively impacted due the Add-In model. Let me clarify:
  1. Conceptual every Add-In is an own and independent (mini) webapplication. Requesting a SharePoint page that hosts <X> Add-Ins, effectively means that the browser is visiting 1+<X> webapplications to load and render the page: first the SharePoint hostweb for the SharePoint hostpage, and next the individual AppWebs for the contained Add-Ins (SharePoint-hosted or Provider-Hosted).
  2. Each Provider-Hosted Add-In (re)enters in an own Add-In launch cycle, starting with App-authentication via the _layouts/AppRedirect.aspx page.
    Our renewed SharePoint based intranet heavily applies the Add-In model, with personalized homepage containing between 2-10 Add-Ins (mixture of SharePoint-hosted and Provider-hosted). In preparation of the Go-Live date, I validated performance and scalability through Visual Studio loadtesting. Due the multiplication of Add-In instances on the homepage there are multiple AppRedirect.aspx calls per homepage visit. On increasing the load the SharePoint server execution of that request became the scalability bottleneck, resulting in CPU to reach 100%. Investigation by Microsoft Premier Support confirmed that the high number (higher as what Microsoft architects had foreseen) of AppRedirect.aspx requests caused the peak in CPU:
    • The high CPU is caused by triggering of Garbage Collector
    • Garbage Collector is triggered due large managed heap, with int64 array datastructures
    • The int64 array datastructures are allocated by App Authentication, to encrypt and decrypt SharePoint internal certificates

    Note: As this (CPU reaching 100%) was for load well beyond both the expected / typical as the peak load, it was not needed to qualify as a No-Go for our Go-Live.
  3. Each Add-In is included in the page-html via iframe element. Due iframe boundaries, there is no runtime sharing possible of client-side objects and resources: every iframe must load its own required objects in own runtime browser context (can be from browser cache for static resources, if that is enabled at client and server-side).
  4. Be careful with building (or buying) too much self-contained Add-Ins, that all store the resources used by the Add-In in own AppWeb. Typical examples is sp.js. If that is administrated per AppWeb, then this heavy library will be retrieved multiple times: typical from the hostweb for standard SharePoint handling, and next from AppWeb(s) due Add-In usage. Due different urls, the browser does not recognize them as same resource, that is already retrieved. On each 'first' visit scenario this will result that the browser will retrieve the same resource multiple times, despite that it is already retrieved before and cached in browser.
  5. Resources that are provisioned as Add-In rootcontent are not included in the blobcache. The effect of this is twosome: [1] SharePoint does not cache the content in blobcache, and on every request must get it again from SharePoint content database; and [2] retrieved resources do not include the ‘max-age’ cache-control header setting (see Max-age cache-control setting for SharePoint content), and therefore the browser must every time ask the webserver whether client-cached resource is still valid or changed on the webserver side. Which in case of static resources (e.g., jQuery library) typically will not have changed, always responding with HTTP 304, and therefore wasting requests and network bandwidth + time.
    Via Yammer Office 365 Network I’ve inquired how-to reduce the number of 304 responses for an Add-In, but apparent this answer is not known as no answer is given - also not by any of the connected Microsoft Office 365 architects and engineers.
  6. Due own appdomain's, no sharing of http-connections across hostweb and the Add-Ins, and as result also no sharing of http-authentication context (see SharePoint App-Model + NTLM results in more 401’s).
  7. Client-side altering of the page-DOM results in a reload of all Add-Ins. This is standard iFrame behavior, implemented as such in all current browsers (E.g. iFrame reloading when moving it in DOM).
All of the above enumerated performance-degradation aspects are inevitable when utilization of Add-In model. Our end-users on average are confronted with one or more 'Working on it...' spinners when they open up their homepage filled with Add-Ins. We managed to mitigate for a large part by combination of some asynchronous behaviour, lazy loading, and enforce the Add-Ins to retrieve resources from shared location (hostweb, but can also be a CDN - internal or SharePoint static).
Once we're enabled to utilize the new SharePoint Framework, we will evaluate which of the Add-Ins can be migrated to that new model and thus break out of the iFrame boundaries + constraints. At minimal the SharePoint-hosted Add-Ins are good candidates for migration to SharePoint Framework based solutions.