Monday 24 June 2013

SP2013 host web apps: provisioning fields and content types

Continuing my little diversion into SharePoint “host web apps” or “Full Control apps” (i.e. apps which provision to the host web) within my larger series about apps, today I want to look at provisioning fields (site columns) and content types – but provisioning them into the host web, rather than the app web. Just to explain where we are in my overall series, here’s the evolving table of contents:

  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
  8. “Host web apps” – provisioning fields and content types [this article]
  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

The idea of provisioning fields and content types to the host web are important techniques for host web apps - since if we can have an app which creates fields/content types AND can provision files to the host web (using the techniques in my previous article), then we could use an app to deliver the building blocks for typical SharePoint collaboration solutions.

As ever, this will only be possible 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

N.B. At this point, you might be interested in the “Should you do this? Deciding between host web apps/sandbox/farm..” section of the previous article.

Challenges when provisioning fields and content types to the host web

I think if we’re going to build apps like this, then we’d probably want some helper methods which can:

  • Provision fields (as site columns)
  • Provision content types
  • Add fields to content types

As before, I’m using JSOM code in the default page of my SharePoint-hosted app – this could be adapted to something different if required. Some challenges I noticed were:

  • It doesn’t seem possible to be able to create a content type with a specific content type ID with CSOM – perhaps I overlooked something, but in any case it does seem possible to obtain it with a later call
  • It seems you have to re-fetch any fields and content types after initial provisioning in order to use them – you cannot use the objects returned from CSOM/JSOM methods. If you try this, it seems CSOM gives you cut-down objects which don’t have some members, and this causes errors like this:

    Have to refetch ctype

How to: provision fields and content types to the host web

The code below is a little bit spaghetti-fied, due to it needing a chain of CSOM commands – an improvement would be to move the code over to using promises and jQuery’s deferred object. As it is, some of our methods need to be called in success callbacks since, for example, before we can add the field to the content type we need both to exist.

It also took me a while to realize that I needed a reference to the actual SP.Field to be able to use SP.FieldLinkCreationInformation, and that whilst I could probably obtain my content type’s ID after creation and then fetch it using this ID, simply iterating all the content types and finding mine resulted in the same number of CSOM calls. Anyway, here’s the code I used:

** 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 just like last time, my app has some sample UI which confirms the steps which have been taken:


The result

Now when we go back to the host web, we see that our field and content type have indeed been provisioned:

Provisioned field Provisioned content type

..and the field has been added to the content type, so it is ready to use:

Field added to content type

Download the code

You can download the full Visual Studio project with the code I used for these two articles from here – download the code.


Richard Walsh said...

Come back declarative CAML all is forgiven!!! Are these sort of "solutions", provisioning the basic building blocks of SharePoint that we have been using for years, in an even more horrendous way than CAML (via CSOM)really a new development paradigm for SharePoint?

The decision by Microsoft to "deprecate" Sandbox solutions, previously the golden child SharePoint 2010, is a really poor decision in my view. I'd love to know the justification for all of these changes within Moicrosoft. And for other compelling reasons, SharePoint hosted apps are better off avoided - just say no!,_are_terrible.aspx

Chris O'Brien said...


Yes, quite! It's a pretty horrible development model if you do decide to go down this route for any reason. However, I'm trying to be clear that I'm not recommending it as such - see my "Should you do this?" section of the previous article if you haven't already.

As I discuss in that post, I'm also expecting Microsoft to change the landscape between apps and sandboxed solutions (again) in the future - there are too many core scenarios which are difficult to deal with, leading to the types of workarounds I'm detailing here.

In terms of limitations with SharePoint-hosted apps - Sahil has good points in the link you provide (even though he does owe me dinner!). One approach to help with ALM/upgrading app webs (Sahil's 1st point), is the idea of storing files (e.g. master pages, CSS, JS etc.) externally instead - see Azure is the new SharePoint "layouts" directory for an example.

But for enterprise clients not on SAML auth (Sahil's 2nd point), I still think SharePoint-hosted apps can be compelling. No server infrastructure to provide, no Azure components to worry about, no debates about running costs or subscriptions - it just works out-of-the-box. Personally I think each client requirement should be assessed, and the app-hosting model decided accordingly - frequently I think there's a place for each.

Good discussion :)