månadsarkiv: juli 2014

AppLoader Concept for SharePoint apps

In this post I want to share an unusual, nevertheless interesting conceptual idea of loading content from SharePoint 2013 apps on many pages. The original awesome concept was proposed and developed by my colleague Martin Villysson at Bool.

The problem we are trying to solve

SharePoint apps are great to extend functionality in SharePoint and integrate other systems (full page apps available through Site Contents), they also provide tools to enrich the default SharePoint experience by App Parts (Client Web Parts) and Custom Actions (additional menus).

One of the biggest shortcomings of that model is the need to add app parts on all pages where it is needed. Let’s say, we want to have some app parts present on every single page in our whole SharePoint tenancy, to provide a consistent look and feel (e.g. navigation, notifications). Traditionally, on premises, we have added user controls in our customized master page. In SharePoint Online that is impossible. The complicated workaround is to add those client web parts (app parts) on every page, be it manually or by automating it (powershell or app). It will require updating all pages. Nevertheless, it will not work on Out-of-the-box application pages (pages from layouts folder). It becomes even more unacceptable when you realize that your app must be added as an app instance on every single site (SPWeb) in your tenancy. 

Towards a solution

Allright, we don’t want to have thousands of app instances of the same app. What we can do is to use Tenant scoped apps (Tenant Apps). Then we’ll need only one app instance. But wait, app parts from a tenant app are only available in the parent site (HostWeb), meaning – App Catalog. That’s not good. So what Martin found in the SharePoint internal javascript code is using of _layouts/15/TenantAppInfo.ashx, a http handler that provides information about all Tenant Apps and their custom actions.That’s how the idea of the AppLoader was born.

Vesa Juvonen

After we had created a working Proof-of-Concept of the AppLoader concept, I met Vesa Juvonen at the SharePoint Conference in Las Vegas and introduced this idea to him (although I didn’t call it AppLoader). He liked it although he pointed out that this TenantAppInfo.ashx is an internal utility only in SharePoint and it is not supported by Microsoft. That’s correct. There is even almost no information about it on the Internet. But I got a feeling of Microsoft that they are willing to hear feedback and improve the product. Vesa encouraged me also to blog about it. So now I am telling about this idea. I hope to hear feedback about it. Unfortunately I cannot share the source code of the working Proof-of-Concept solution.

AppLoader Concept in colors

The AppLoader Concept is quite simple. Look at this picture:

apploader-concept

 

The solution contains a custom Master Page (blue) that references a javascript file called apploader.js (red). This file initializes the whole process. Tenant Apps (green) are the apps that an administrator has installed in the App Catalog and deployed to the whole tenancy. TenantAppInfo.ashx (black) is a handy but officially unsupported OOB service utility (http handler) that returns a json-formatted list of all Tenant Apps (green). AppLoader (red) receives the app list (black) and renders it on the Page (blue) inside new iframes (red). The page a user has navigated to can be any page (wiki page, publishing page, application page, really any page).

To summarize the colors in the diagram: red is our javascript code, green are all the tenant apps and their content, black is the utility and its output, blue is a sharepoint page and its underlying component (master page).

The steps in the AppLoader process:

  1. Make an ajax request to TenantAppInfo.ashx using XHR (XmlHttpRequest)
  2. Receive the app list
  3. For every app information, render app part, or inject css and javascript references. 

 

Reading what to render on the page

You probably have already have tried to navigate to _layouts/15/TenanAppInfo.ashx while reading this post, I know you are curious. Then you’ve noticed that there is no information about app parts. So you may ask: how do we know what app parts to render and where to put them in the page, and how do we know what resources (css and javascript files) to inject on the page. Well there is no information about it in the apps list. But if you have an app with custom actions you’ll see that they are listed in this json-formatted list we receive from the TenantAppInfo.ashx. So the solution is the brilliant idea of my colleage Martin to define custom actions in the app. CustomActions contain a ActionUrl. The ActionUrl points to the url to render (app part page) or to inject (javascript or css file). The apploader.js reads the ActionUrl in the Custom Actions for every app information and takes action upon it (rendering an app part iframe, or injecting a javascript or css file). That’s it. 

Usage and Limitations

This bright idea takes advantages from a huge SharePoint API (that contains a lot of good but not supported parts) to make using of apps in Client Application Model solutions more pragmatic and still provide a consistent design and behavior. By consistent design I mean same parts like additional navigation, notifications etc in the whole Intranet. The AppLoader renders and injects whatever you have rolled out to your whole tenancy (Tenant Scoped Apps) and that on every page (!). It also improves the perceived performance of the page load, because it renders app parts (iframes) after the main page has been loaded preventing freezing of the page. 

There are of course some limitations in the AppLoader Concept. Today we cannot rely on the TenanAppInfo.ashx API (because it is not supported and future updates can break solutions). We have to define our own custom actions in the apps. That means we can only use our own apps, it will hardly work with the apps installed from the Office Store. On the other hand, your customer will not want to have generic apps from the Office Store to be a part of every page on their intranet.

Configuring VirtualBox for SharePoint-Hosted Apps

Recently I have switched from VMWare to VirtualBox for my SharePoint Development. So far it really works good. I have prepared this guide for configuring VirtualBox for SharePoint-hosted apps. That means we need a new adapter with a static ip address. All the steps done inside the virtual machine are applicable for VMWare and Hyper-V, too. This guide does not cover the full configuration of the app environment, it covers only the network and dns settings needed for SharePoint-hosted apps on Premises in a Development machine.

In VirtualBox open Preferences:

002-vbox

In Preferences, click on Network, then on Host-only Networks, click on “plus”

003-vbox

After a new host-only Network adapter has been created, click on the screwdriver image to configure the network:

004-vbox

Remember this ip address, you can alter it, of course. Or use this: 192.168.64.1, then you can have the same settings in your environment as I have:

005-vbox

Go on to the settings for your Virtual Machine. Enable Adapter 2, as shown on the picture below.

006-vbox

The rest are the settings in your virtual machine. Open Network Connections in the Control Panel. For the newly added Network Adapter (Ethernet 2), open Properties:

007-vbox

Then open Properties for “Internet Protocol Version 4 (TCP/IPv4)”

008-vbox

Remember the ip address for you VirtualBox host-only Network? I have 192.168.64.1. Increment the last number (192.168.64.2) and use it as the ip address for your adapter. The default gateway is 192.168.64.1 as the the VirtualBox host-only Network. The DNS Server should be the same as the virtual machine, the same adapter: 192.168.64.2:

009-vbox

Open DNS Manager, right-click on Forward Lookup Zones and start the New Zone Wizard by clicking on “New Zone…”:

010-vbox

Follow the steps in the wizard:

011-vbox

Choose “Primary Zone”:

012-vbox

Keep the default setting: “To all DNS Servers running on domain controllers in this domain:

to-all-servers-vbox

Write your app domain. I use takanaapps.local:

014-vbox

Choose “Do not allow dynamic updates”:

015-vbox

Then finish the New Zone Wizard:

016-png

In the new forward lookup zone (takanaapps.local), add a new wildcard cname entry (alias):

017-vbox

Just add an asterisk and point it to your main domain (takana.local in my case):

018-vbox

After that you should be able to ping any subdomains of your app domain (xyz.takanaapps.local, abc.takanaapps.local):

019-vbox

When you start adding apps to your sites, you should add app sites to your local intranet zone (to be automatically signed in in apps webs). This setting in IE will affect Chrome as well. Go to the Options in the Internet Explorer:

020-vbox

In the Security tab -> Local Intranet, click on Sites:

021-vbox

Click on Advanced button:

022-vbox

Add your new app domain with an asterisk in front of it to the “Websites” of the Local Intranet:

023-vbox

Sources

Rare bug in SharePoint with IE9 when account names have commas

Configured a certain way, Active Directory will generate account names like so: ”Lastname, Firstname”. Although SharePoint strongly recommends you not to use account names with special characters, it seems to mostly be able to handle this.

Now, user links generated with SharePoint’s renderUserField look something like this:

Which works perfectly fine. However, with commas in the account name, the account name part of the link will instead look like this: ”turing%2C%20alan”. URL encoded comma is %2C and space is %20. So far, so good. Try it in Firefox, Chrome, IE10+, no problems. Try it in IE8, works great. But not IE9. Clicking the link in IE9 sends you to a url containing ”turing%252C%20alan”. Spot the error? %252C looks a lot like double encoding. And it is. But why is this only a problem in IE9? I worked my way through many suspects, including encodeURI and escapeProperly/unescapeProperly (yes, these do exist in SharePoint). Nothing came up. And the odd thing is that the URL in the link I click doesn’t match the URL I end up at. This because of the onClick handler, of course!

After a lot more work, I find out why this bug is only active in IE9. There’s a piece of code, triggered by the click handler, that decodes the URL encoded link, does some stuff with it, and encodes it again. This code is blocked by two conditions. It is only reached if the MDS is on and the browser is Internet Explorer 9 or less. MDS doesn’t work in IE8. That only leaves IE9.

But why the double encoding? The thing is, encodeURI will not touch commas, they don’t need encoding. Try it out in your console:

And of course, if you encode something and then decode it the same way, you should get the original string back, right? What if you use encodeURIComponent to encode, and encodeURI to decode? Bad things happen. Because encodeURIComponent _does_ encode commas. So lets say you know a certain string is encoded already, and you want to decode it, do some stuff with it and encode it again. You might write this:

Try that code with this URL: ”http://example.com/turing%2C%20alan/”. You should get ”http://example.com/turing%252C%20alan/”. Mystery solved!

But that just raises another question, really. Why was the comma urlencoded in the first place? The culprit can be found in SharePoint’s ”init.js”.

Back to the onClick handler. It calls a function called GoToLinkOrDialogNewWindow, which uses the href of the a tag you clicked and, amongst other things, creates a URI object from it. URI is a type of object defined in ”init.js”, and has lots of nifty functionality. It automatically encodes its content too, and when you call getString on the object, you get a nicely formatted URL string. Except, of course, when there’s a comma in it. You see, URI doesn’t use encodeURI. Instead, it breaks the link up into parts, a bit like this: http-:-//-example.com-/turing, alan/ (using – as a delimiter). It then fastidiously encodes each component, of course, using encodeURIComponent.

So who’s wrong? No one, really. The problem is that one part of SharePoint assumes a URL to be encoded using encodeURI. Another part of SharePoint encodes the URL by looping over parts of it and calling encodeURIComponent. Communication breakdown.