Wednesday, 29 May 2013

SP2013 host web apps: provisioning files (e.g. master pages) to the host web

Here in early summer 2013, it’s a slightly strange time in SharePoint development land. The message is that sandbox solutions are “deprecated” in SharePoint 2013 (however you choose to interpret that) and that we should build apps where possible – however, apps currently cannot do many of the things that sandboxed solutions can. One key difference between apps and sandboxed solutions, of course, is that when you provision fields/content types/files etc. in your app they are created in the app web – not the “host web”. For many requirements, this “isolated space” idea works fine. However, when you really want your artifacts to exist in the day-to-day areas of SharePoint that users go to (i.e. the team/project/My sites that become known as host webs in the app world) then you need a different approach.

If you’re no longer comfortable using the sandbox, then what can we do? Well, one option to consider is that apps CAN sometimes “provision to the host web”. This article looks at this idea, but first here's a reminder of where we are in the overall series:

  1. SharePoint 2013 apps – architecture, capability and UX considerations
  2. Getting started – creating lists, content types, fields etc. within a SharePoint app (provisioning)
  3. Working with data in the app web, and why you should
  4. Access end-user data (in the host web) from a SharePoint 2013 app
  5. Rolling out SharePoint 2013 apps to the enterprise - tenant scope and PowerShell installs
  6. Azure is the new SharePoint ‘_layouts’ directory
  7. “Host web apps” – provisioning files (e.g. master pages) to the host web [this article]
  8. “Host web apps” – provisioning fields and content types
  9. Deploying SP2013 provider-hosted apps/Remote Event Receivers to Azure Websites (for Office 365 apps)
  10. Working with web parts within a SharePoint app
Anyway, apps can provision to the host web IF:

  • The app requests (and is granted) “Full Control” permission of the host web
  • CSOM code is used for provisioning, rather than standard Feature XML

All of a sudden, apps can now be used as the vehicle for deploying “regular” SharePoint functionality – perhaps components that are used in typical collaboration solutions. The code/solution in this article is taken from my “Deep-dive on SharePoint-hosted apps” talk at the SharePoint Evolutions Conference, and this article is the first in a series of short posts on such “host web apps” (within my wider series on SP2013 apps). But first..

Should you do this? Deciding between host web apps/sandbox/farm..

I think this approach has a place – especially if you are paranoid about the life expectancy of sandboxed solutions, or someone is insisting that the app model is used. However, my feeling is that we are effectively exploiting a loophole here. I’m sure Microsoft did not particularly intend apps to be used in this way (as evidenced by difficult CSOM-based deployment model), but, possibly because of other concerns, they have robust mechanisms in place such that it isn’t proactively blocked. Me? Well, personally I feel that if the client requirements steer you towards working in the host web, then apps aren’t the right vehicle – if you’re cloud-focused, then I believe you should be using a design centred around the sandbox. Despite the "deprecated” tag I think Microsoft will have to extend the app model before they can really remove this option. In other words, I think we should understand that we are in a transition period and new development approaches will become available – but I won’t feel bad about using the best tool for the job right now.

I should add that this might not apply to product development – an area which I currently do not have to worry about. My friend Doug Ware is building an app based around the host web, and has dug far deeper into this than me. We’ve previously debated this topic in our blog posts – you can my version (which links to his posts) at SharePoint apps: working with the app web, and why you should. You’ll see that I’m effectively softening my position slightly in this post.

How to: provision a master page (or any file) to the host web

In this example, I’m choosing to provision a master page – but the approach works for other file types too. Arguably the best approach is to provision the file, initially at least, to the app web. This works because later on we’ll need to fetch the file contents from somewhere, rather than declare the entire file contents directly in a JavaScript variable (not very practical). So, we add the file to our app and use a Module element to provision it into the app web. I found that provisioning with a .txt extension was best at this stage (more on this later):

Provisioning to app web initially

The code

Then we need a wodge of CSOM code – specifically JSOM in my case. I’m using a SharePoint-hosted app, where the code executes on page load of the app default page. In the code we have to pull a few tricks – firstly we make a jQuery GET request to the .txt file in the app web, in order to obtain the contents. N.B. This was the reason we provisioned it with a .txt extension at first – for some file types (e.g. .master, .aspx) you might find that the file contents are not what you expect. This can happen because the page could not be executed/parsed properly by SharePoint, i.e. a runtime error occurred because you effectively browsed the master page/page layout/whatever directly. This undesired behavior goes away if you are simply requesting a .txt file.

Then we use JSOM to open a connection to the host web. We do this by passing a relative URL to the host web to the SP.ClientContext constructor, instead of asking for SP.ClientContext.get_current(), which would give us context in the app web where our page is running.

Our JSOM code then uploads to the host web (via a method which can be re-used to provision any file to any path in the host web), and just for good luck we go ahead and set the master on the host web. The code below has no external dependencies, and should work fine if you paste it into your app:

** N.B. My newer code samples do not show in RSS Readers - click here for full article **

Running the app

Once our app is built and we add it to a site, the person adding has to accept the Full Control permission request:

  Full control app permission requirement

And, since the model here is that our JSOM code executes when the page is loaded, our master page is indeed provisioned when the user navigates to the app. My sample code presents show some simple UI to confirm this:

File provisioning success UI

The result

Now when we go back to the host web, we see that our master page has indeed been provisioned to the Master Page Gallery:

Master page provisioned

..and because we set it to be the default master page, any branding changes in this master page (such as a red bar in my case) have been applied to the site:

Master page changed

So, if you really want to avoid sandboxed solutions or proactively want to use apps, then you can see that these CSOM techniques can be useful. In future posts, I'll follow up with further code for other common scenarios.

Download the code

You can download the full Visual Studio project with the code I used for these two articles (on host web apps) from here – download the code.

10 comments:

Magnus Hansson said...

Hi Chris !!
Great example how to provisioning master pages and other artifacts to SharePoint. Will be of great help I am sure.

Thanx
//M

Pascal Van said...

Great article !!

Anonymous said...

This was a great article at the perfect time. I was just asked to do the exact same thing. Is there anyway you can upload your code to the site? Being a newbie to 2013 App Model would like to follow the code.
Thanks in advance,
Andrew

Matthias Einig said...

Hi Chris!
I don't want to kill the messenger but such a deployment approach feels like a big step backwards and error-prone.
Your solution in this post, though no doubt solved technically great, seems to me like an ALM nightmare.
What if you have to upgrade the masterpage? Re-deploy the app and then navigate to all SiteCollections to re-provision?
I am really hoping that MSFT gets going quickly to provide a real alternative for sandboxed and farm solutions. Otherwise I fear that in 3 years from now we talk about the App model beeing deprecated too ;)
Cheers
Matthias

Chris O'Brien said...

@Anonymous,

I've now uploaded the code and added the link at the end of the article.

HTH,

Chris.

Chris O'Brien said...

@Matthias,

Yes, I don't disagree at all. ALM would indeed be a big concern for "site infrastructure" files such as master pages (although instead, you could reference them externally as discussed in Azure is the new 'layouts' directory). I could believe, however, that some folks will find this file provisioning technique useful in some app scenarios - maybe for provisioning other types of files (e.g. Office docs)?

In general, I also hope this development model does not become common. In the "Should you do this?" section, I mention that I feel the approach is something of a loophole. Despite the deprecated tag, my personal view is that (here in June 2013) I'd prefer sandbox development when provisioning to the host web is required - it's just that I would avoid code wherever possible.

Effectively I'm writing these posts in "response to demand" :) I've had a few questions along the lines of "if you *really* didn't want to do sandbox development, could you get an app to do X?". It's a good trick to have in the toolbox. But going forward, I'm also expecting Microsoft to change things between the app model and sandboxed solutions.

Thanks for the informed comment, good discussion :)

Cheers,

C.

Matthias Einig said...

Glad that you see it also that way (and I didn't doubt it actually ;) ) I read your section about "Should I do this?" of course!

Unfortunately the AppModel is still not fit for replacing farm or even sandboxed solutions especially but Microsoft will evolve it quickly I suppose...

I think even though many developers fear and loath all the XML in ordinary solutions it has some advantage having a standardized declarative approach to do common things (i.e. creating columns and content types like you write in the next article of this series) instead of using a JSOM.

So at least I am hoping to see something similar coming up in the App model. But maybe I am alone with that wish ;)

BTW, have a look at the two very interesting posts of Richard diZerega which also try to solve problems with SPO/Office365 based solutions:

SharePoint 2013 App Deployment through "App Stapling"

Self-Service Site Provisioning using Apps for SharePoint 2013

Cheers and keep up the great posts!

Matthias
@mattein

Susan C. said...

I attempted to download your VS project but it says the file has been removed, renamed or is temporarily unavailable. Can you check into this and see if there's any way to get this working again? Thanks!

Chris O'Brien said...

@Susan C,

Apologies, link now fixed.

Thanks!

Chris.

New blogger said...

Chris, great article. New to the App Model and this is a great stepping stone for me.