SharePoint 2013 Hosted Apps – Do they really work? Part 1

Recently I have spent some time working through building and converting demonstration code across to SharePoint 2013 Apps and have a fun time learning what can be done and really what can’t be done. This post is based my practical experience so far of trying to use “SharePoint Hosted Apps” only. The reason for this was to make an App that would work on-premise and on Office 365 with no dependency on managed code but to use pure JavaScript.

So to create a new SharePoint 2013 Hosted App you need to ensure that when you create the project in Visual Studio you select the correct option.

Once the project is created you should get a structure similar to this:

The basic construct is the following:

  1. Feature Folder – Normal SharePoint Feature dialog you have used in the previous tooling
  2. Content Folder – Any specific content that will reside in the App Web, by default the App.CSS file
  3. Images Folder – Images that will reside in the App Web
  4. Pages Folder – The core pages that will reside in the App Web (Core User Experience)
  5. Scripts Folder – Contains all JavaScript files, such as jQuery and the core App.js, once again all hosted in the App Web
  6. AppManifest File – Base configuration and permission sets for the App

If we deploy this solution as is, it will render values that are called from the App.js file. This will display your current display name.

This page is loaded from the App Web, this is the separate web site that gets stood up as part of the new App Model. A SharePoint 2013 Hosted App when deployed does this automatically and crea6es a URL similar to this:

So the first things to note here is that the code and other assets do not live inside SharePoint, so that changes the overall design considerably. So the user experience becomes slightly more complicated than before. Whereas we would write code either full trust or even sandboxed code it would be deployed directly into SharePoint, so simple things such as deploying files like images, CSS or JavaScript to the style library was still supported, now it is not. Sean McDonough has a great blog post about imaging rendering and SharePoint 2013 Apps in General, I would suggest a read:

http://sharepointinterface.com/2013/01/22/custom-ribbon-button-image-limitations-with-sharepoint-2013-apps/

So let’s think about an example app we could build. For this demonstration I would like an end user to access a list, see the list items, press a ribbon button, and then popup a dialog over the top listing out the selected items only and then allow the end user to perform some action. I can hear you thinking this is going to be easy. Write a full trust solution that does the following:

  1. Deploys JavaScript, CSS and Images
  2. Adds a Ribbon Button, maybe as a custom “Additional Page Head” control so it shows up on all Ribbon Bars
  3. Uses C# to get the currently viewed list
  4. Uses JavaScript to get the selected items
  5. Opens the Dialog
  6. Loads a custom page, maybe “_layouts” page
  7. Custom Page uses C# to get the currently selected list, renders only the selected items based on what is passed to it

Of course there are many ways of doing this same thing whether using Full Trust C# or Sandboxed Client Object Model code. So how do we do this for a SharePoint 2013 Hosted App. First off let’s look at adding a ribbon button. In the Visual Studio right click he project and select “Add New Item“. From the list select the “Ribbon Custom Action“.

Once selected you are asked to define the type of Ribbon Action. The first thing is where you wish this custom action to reside. The Host Web is SharePoint, the App Web is the funny website that got created in my Office 365 Tenant when I deployed it. As we need this ribbon button to be in the current SharePoint, we will select the “Host Web” option. We also have the ability to scope the action to one of the following:

The interface does not allow for scoping actions to anything other than List Templates and List Instances. Selecting List Template will populate the second dropdown with the available list templates in the SharePoint site that is connected to Visual Studio. If you select List Instance it will populate the dropdown with available lists that are deployed and active in the SharePoint site. For this example we are going to choose “None” as I would like to associate this action to more than one list or template.

The tooling then let’s you select the control location from a predefined list:

This list is great but once again does not list every location you would want to use. You can overtype this with your own values if needed. For this demonstration we will use “Ribbon.List.Actions“, with the control navigation set to the default page.

Visual Studio will then create the custom action object in the project and the “elements.xml” file is loaded and will look similar to this:

The code looks fairly straight forward and what you would be used to seeing, however notice that the “CommandUIHandler” is a redirect to the following URL:

~appWebUrl/Pages/Default.aspx?{StandardTokens}

You will notice it is using a token for the URL, the “~appWebUrl” is a unique one that SharePoint 2013 understands and will replace at the build and deployment time into the full URL of the App Web, so it will end up being something like this:

You will also see an appended query string of “StandardTokens“, this is one of the replacement tokens that are available. This specific one combines five other tokens. “SPHostUrl“, “SPAppWebUrl“, “SPLanguage“, “SPClientTag” and “SPProductNumber“. Sahil Malik has a list of all the tokens that are available in SharePoint 2013 Apps and when they can be used.

http://blah.winsmarts.com/2013-2-SharePoint_2013_apps_replacement_tokens.aspx

Let’s say we wanted to change this mechanism to use a simple piece of JavaScript. SO something simple like this: “javascript:alert(‘Hello World’);“, we would change the XML to be the following:

Now if we build the application is Visual Studio all is well. Now if we try to deploy it something strange happens.

It errors with the deployment saying there are errors in the package. This is because you CANNOT run inline JavaScript inside ribbon actions at all. This is a big difference to the full trust and sandboxed design we currently have in SharePoint 2010. So from a user experience for something like this we would need to explain to the end user that every time they click the ribbon it will take them out of the SharePoint site to perform the task and then we would need to handle through code the redirect back or the end user would be stuck in the app not SharePoint. By default however you will notice that the App Web is styled with a similar chrome to SharePoint itself, along with a link to get back to the site you came from, this will help in the user experience.

So back to performing a redirect, this means we need to write the code in the App Web for getting list items etc. as per our design for this demonstration app. If we change the code back and build and deploy we should be back to the site now. To test the ribbon we can access a list and see in the “Actions” section our new button.

If you click this button it will redirect you to the App Web and show the default page. If we look at the URL we can see the token values:

https://demo-5551df50f2862e.sharepoint.com/sites/appdev/DemoApp/Pages/Default.aspx?SPHostUrl=https%3A%2F%2Fdemo%2Esharepoint%2Ecom%2Fsites%2Fappdev&SPLanguage=en%2DUS&SPClientTag=0&SPProductNumber=15%2E0%2E4454%2E1032&SPAppWebUrl=https%3A%2F%2Fdemo%2D5551df50f2862e%2Esharepoint%2Ecom%2Fsites%2Fappdev%2FDemoApp

This is great as it already passes a lot of information that we would need to us in the App Web, such as the actual site we are in. We can change our Visual Studio solution to also send us further details, such as the ID’s of the selected items, the list ID and name. To do this we need to make changes to the “CommandAction” link. Modify the link to be the following:

Now build and deploy the solution and test the link this time. This time access the list and select a few items as shown below and click the ribbon link and the URL should now be similar to this:

https://demo-5551df50f28632.sharepoint.com/sites/appdev/DemoApp/Pages/Default.aspx?SPHostUrl=https%3A%2F%2Fdemo%2Esharepoint%2Ecom%2Fsites%2Fappdev&SPLanguage=en%2DUS&SPClientTag=0&SPProductNumber=15%2E0%2E4454%2E1032&SPAppWebUrl=https%3A%2F%2Fdemo%2D5551df50f28632%2Esharepoint%2Ecom%2Fsites%2Fappdev%2FDemoApp&SelectedList={B6F5FCC8-5102-4F1B-9F24-D8929162CB51}&SelectedItems=3,2

This time you will notice that we get the list ID and the selected ID’s of the values we selected in the list, so now we just have to wire up the new page in the App Web to display these items in a list view type grid.

This design now means that we need to allow the end user to perform the required tasks such as selecting items in SharePoint, send that to the App Web and then re-connect to the SharePoint site and list or library using the client object model or the REST API features. This logic will be added to the “App.js” file which is referenced in the “default.aspx” page.

The “App.js” file allows us to add any JavaScript or JSOM code to connect or interrogate SharePoint. Be aware that this is a subset of the core API that is available in SharePoint. In the next post we will look at writing JavaScript code in the “App.js” along with the pro’s and con’s to this design.

Liam Cleary

I work as an Associate Director for Protiviti in Virginia. My main focus is to ensure that SharePoint can either natively or with minimal customization meet the business requirement securely. I am currently a SharePoint MVP focused on Architecture but also cross the boundary into Development and Security. I am often found at user groups, conferences speaking, offering advice, spending time in the community, teaching my kids how to code, raspberry PI programming, hacking the planet and sometimes building Lego robots.

You may also like...

  • Stefan Bauer

    Hi Liam,

    great article but I see it a little bit different. I don’t think it’s works as designed because if you insert the javascript function directly you will get a warning that inline javascript is not allowed and you are only able to add hyperlinks.
    You cannot deploy that scenario directly but you will be able to change the action of the custom action after you have deployed the solution.