Home > Development, Office 365 > Appropriate use of AppInstalled for a Provider Hosted SharePoint App

Appropriate use of AppInstalled for a Provider Hosted SharePoint App

Sometimes the clue’s not in the name.

As part of ERM (enhanced Records Management) we are trying to create a minimum configuration solution.  Why?  Well most implementations in the Records Management sphere take three to six, or months, to implement.  Scratch that most ‘enterprise’ software takes about a year to get installed.  That’s a major block to implementation.  What causes this?  You install on a ‘prototype’ and configure; then on a test system and configure; then on production and configure as a minimum.  In fact many enterprises will also have a performance, penetration and pre-production environment as well.  Configuration always takes time and its tricky as you set up servers, services, databases and modify configuration files for all of them.  Get it wrong and you then spend ages wondering is it your configuration or a bug?

Now contrast that with your mobile phone.  You select the app, download it and start.  Configuration, if there is any, tends to be entering some log on details and maybe flipping a couple of options, no more.  Time to implement?  Minutes.

So how do we get the same effect in the enterprise?

Simple we avoid configuration like the plague, we let the application discover and configure itself, much like your ‘plug and play’ hardware has been doing for over a decade now.

Right so when the software installs it should do it shouldn’t it?

There’s a remote event receiver for SharePoint Apps called AppInstalled that’s what we should use, shouldn’t we?

After some experience I think the answer, at least for Provider Hosted Apps, is no to both.

The AppInstalled event has some real shortcomings.

  1. It only ever runs once, when the App is installed, if something goes wrong then it will never run again.  Also if something in the host site changes it will never reconfigure to match.
  2. Its error reporting facility is poor, it is an asynchronous event handler after all, it effectively swallows errors, or rather seems to automatically retry a couple of times, and has no in built display method.
  3. It interferes with the planned running of the App, for example the App Icon does not show.
  4. It has no mechanism for showing progress on what could be a long running event.

In retrospect it seems like AppInstalled was designed for short, sharp actions to be taken that have little chance of failure.  Used like this it works nicely.

So what should we do instead?  The key is that if it fails then it won’t be run again.  We could use the AppUpgraded event but that has all the same limitations.

Hmmm.

We do have something that is guaranteed to run every time someone accesses the event and that’s the Home Controller’s Index action.  We could use that.  The last version did just that and it works nicely.  It checks if the App is configured and if not starts configuring it.  However it turns out that at least two mechanisms do not invoke this action.

  1. Remote Event Receivers, e.g. Item Added or Field Updated.
  2. Unit Tests.

Even one of these is enough to remove the responsibility from the Controller, where it did, in retrospect seem a bit out of place.

So we moved it again.  ERM uses a ‘service’ layer to talk to its twin repositories, the ‘native’ Records Repository and its own Management Repository.  So now it is its job when instantiated to check if the App is appropriately configured and if not do something about it.

This means that:

  1. It runs as often as is needed therefore it picks up configuration changes as needed.
  2. It will always be invoked by something else so it off loads the error handling to that all it now needs to do is handle its own errors if it can and if not throw them up the stack.  Perfect error handling is now being done in the correct place.
  3. The App will just install with less chance of anything going wrong, installation has been simplified further.
  4. Handling progress, if its a long running event, can be delegated to the view that is invoking the service creation, again perfect.

Now all we need to do is move the code to the appropriate place and rejig the unit tests.

Cheers

Sebastian

Leave a comment