chess-strategy.jpg

Working With (and Around) SharePoint 2013’s Minimal Download Strategy

Sean is a senior consultant at ThreeWill. He has over 16 years of experience developing web applications. His primary passions are in usability, group collaboration, project and process automation, data visualization, and social media tools. He is an MCSD in Web Applications and an MCTS in SharePoint Application Development.

Minimal Download Strategy

The SharePoint team added a new feature for 2013 known as “Minimal Download Strategy,” or MDS. This is a bolt-on feature that gives SharePoint Single Page App (SPA) behavior. This SPA behavior improves SharePoint’s performance, reduces server load, and offers a smoother user experience by eliminating wholesale page reloads on every link click. It’s the experience users associate with contemporary “Web 2.0” applications. SharePoint has never had a good performance or server load story, even when well designed and properly tuned, so MDS represents an important leap forward in these two areas. You can learn more about MDS from Microsoft’s MDS overview on MSDN.

Making the Magic Happen

SPAs are typically designed from the ground up using client-side MV* frameworks such as Angular, Backbone, or similar that manage their routing behavior. SharePoint, on the other hand, has retrofit this behavior using several layers of trickery:

  1. The first is a server-side MDS “engine” (Microsoft’s term) that’s hosted by SharePoint’s _layout/15/start.aspx page. It determines the content deltas between the browser’s current page and the newly requested page.
  2. The second is a client-side MDS “engine” that’s hosted by the _layout/15/start.js JavaScript file. It communicates the current page contents and the new page’s URL to _layout/15/start.aspx, and handles the SPA-style partial-page rendering of the delta content returned by _layout/15/start.aspx.

These two MDS engines give SharePoint a convincing SPA feel. While the experience is not as snappy as it would be with a designed-from-the-ground-up SPA, it is noticeably better than SharePoint 2013 without MDS. Creating a credible SPA experience as a retrofit like this is an impressive accomplishment…when it works.

Where the Illusion Breaks Down

MDS is capable of handling most page transitions, especially between out-of-the-box pages. As you add custom code to your site, the risk of MDS failure increases. When MDS can’t handle a page transition, user experience and server load are actually worse than with MDS disabled. Here’s why: both MDS engines require processing time to work their magic. When it works, this processing short-cuts around some expensive page load operations on both the server and in the browser. But when it doesn’t work, MDS has to drop back and re-route the request as a full, non-MDS page load for the requested page. In these cases the short-cut becomes a long-cut: the request incurs all the overhead required by the MDS engines up to the point that they determine they can’t handle the request, and then a full, load-and-render-the-whole-page request for the new content. The long-cut doesn’t double the page load time, but it’s more than a bit noticeable to the user and puts significant extra load on the server.

Can I Get a Volunteer From the Audience?

So should you enable MDS for your SharePoint 2013 site or not? The answer is “it depends.” If your site contains zero customizations, MDS is a slam-dunk. The more customizations you add, the bigger the risk MDS will become counter-productive. If you’re developing the custom code used in your site, you can make it MDS-compliant per Microsoft’s recommendations. Following is a list of common causes of MDS failure (from the MDS overview), with my notes on how to avoid each of them in-line:

  1. The newly requested page has a different master page than the current page. This makes complete sense: requesting a page with a different master page than the current one means that the most basic structure of the page needs to be updated. These changes are too fundamental for MDS to handle. Keep your master page options as simple as possible to avoid this risk.
  2. The current master page has been updated since the last page load. Also makes sense for the same reason mentioned above.
  3. The current or requested page contains “non-compliant” content:
    • The page uses the ASP.NET 2.0 framework. The MDS server engine is only able to run its magic on pages running on ASP.NET 3.5 or later. Hopefully you aren’t deploying ASP.NET 2.0 pages to SharePoint anymore, but if you are, stop. No, seriously–stop.
    • The page uses CSS or Javascript files that aren’t registered with the MDS engine. For solutions deploying custom mark-up (in custom application pages), you can make MDS aware of CSS and JavaScript files by using the standard CssLink, CssRegistration, and ScriptLink server tags. If you aren’t in the habit of doing this already, see MSDN’s article on modifying SharePoint content for MDS for more info.
    • The page contains “illegal” HTML. At the very least both <script/> and <style/> tags are considered illegal; as mentioned above, use the server-side CssLink, CssRegistration, and ScriptLink tags instead. “Illegal” HTML may cover other conditions that might prevent the MDS engine from correctly parsing the page. Avoid unclosed block-level tags, missing <head/> or <body/> sections, etc.
  4. The current or requested page contains “non-compliant” controls:
    • The control is not in the MDS engine whitelist. “Whitelisting” is achieved by registering resources with the SPPageContentManager class, using the RegisterClientScriptBlock(),
      RegisterClientScriptInclude()RegisterInlineStyle(),
      and similar methods. See MSDN’s SPPageContentManager API reference for more details.
    • The control assembly is not marked as MDS-compliant. Assemblies that contain custom controls have to be marked with the Microsoft.SharePoint.WebControls.MdsCompliantAttribute to alert the server-side MDS engine that they have controls that support MDS. Reference MSDN’s article on modifying SharePoint content for MDS for examples of how this is done.
    • The control’s class doesn’t have the MDS attribute. Server-side control classes also have to be marked with the MdsCompliantAttribute to alert the MDS engine that they support it. This should only be done if all other compliance steps mentioned here have been taken.

Pulling a Rabbit out of the Hat

As a developer of full-trust farm solutions for SharePoint 2013, you have a great deal of control over whether or not your custom code and controls cause MDS to fail. Follow the instructions provided in the links above and everything should be ducky.

However, if you are developing SharePoint 2013 App Parts for SharePoint-Hosted or Provider-Hosted solutions, the MDS story for now is bleak. At the time I’m writing this, the control used by SharePoint to render embedded App Parts on a page causes MDS to fail: Every. Single. Time. Not only does it fail, but the failure appears to be caused by SharePoint’s internals; there’s no way to resolve this by making App Parts MDS compliant. We dug into the SharePoint 2013 source using .NET Reflector and discovered that the SPAppIFrame control used to render App Parts emits a raw <script/> tag using the HtmlTextWriter class. This makes the SPAppIFrame control non-MDS compliant per Microsoft’s own recommendations listed above. You can find detailed technical information about this issue in my colleague Eric Bowden’s StackOverflow post on the subject. ThreeWill has a support ticket open with the SharePoint Online team to investigate this issue, but it probably won’t be an easy fix, so we don’t expect a resolution anytime soon.

Unfortunately, this doesn’t leave many options for Hosted Solution developers for now:

  1. Use Apps instead of App Parts. There’s significant business value in the capability of adding custom, configurable app logic (i.e. web parts) to SharePoint pages. But if you can architect your solution to keep your custom logic confined to it’s own pages, you have the opportunity to introduce your own “proper”(read: non-retrofit) SPA behavior by using Angular, Backbone, or another SPA framework within your app. Developing your own SPA logic reclaims significant control of application flow and performance; don’t discount this option just because “the client expects web parts.”
  2. Avoid routing requests to non-MDS-compliant pages through start.aspx. For example, if your site home page contains custom App Parts, any links to that page from your top navigation, quick links, wiki pages, and external sites should route directly to the <site>/SitePages/Home.aspx URL instead of using <site>/, which will cause it to route through start.aspx. Consider validating all of your navigation links, and any that contain start.aspx should be replaced if the link target includes a custom App Part.
  3. Disable the MDS feature on your SharePoint web. MDS is packaged as a feature on your SharePoint web, and it’s easy to disable. This is “the nuclear option”, but for sites with significant customizations on multiple pages, the overall performance may very well improve with MDS disabled.

 A Tip of the Hat

While it’s easy to pile on Microsoft for the shortcomings above, the fact that they’ve attempted this at all deserves some applause. SharePoint, even in it’s 2013 form, has a huge base of legacy code and changes to deal with, and MDS as it exists is an important first step in making SharePoint behave like a modern web application.


Related Posts

Sean HesterWorking With (and Around) SharePoint 2013’s Minimal Download Strategy