Atlanta Cloud Saturday – September 26th, 2015

Please join us at the Microsoft Greater Southeast District office in Alpharetta, GA on September 26 for the first annual Atlanta Cloud Saturday!

The goal of this event is to give you an overview of some of the cloud technologies being used today. Topics include Amazon Web Services, Azure, Office 365, Salesforce, IBM, DevOps, and more. Check out the great list of speakers and sessions (http://atlanta.cloudsaturday.com/sessions/) and be sure to register soon (https://www.eventbrite.com/e/cloud-saturday-atlanta-2015-registration-18034390347).

I hope to see you there!

Architects: SharePoint is a Platform, Treating it as only a Service is a Mistake

Last week my friend Andrew Connell wrote a rather provocative post titled Developers: SharePoint isn’t a Platform, SharePoint is a Service. In it he makes some persuasive points and advises people to move their front end development out of SharePoint. In this post I’d like to deconstruct a few of his points and explain why I think his advice in this regard is not very good.

The Past Product Engineering Failures at Microsoft Happened

A large portion of his post concerns the undeniable fact that Microsoft has offered a series of customization models for SharePoint over the years with varying degrees of success. I agree with just about everything in this section.

There has been a series of models from the SharePoint team, and, in some respects, Microsoft has shown a shocking lack of integrity as a vendor and business partner in the way they cavalierly advised customers to do things certain ways only to later say ‘whoops! We changed our minds’. Taken from a certain angle it’s almost unforgiveable.

On the Other Hand

I think everyone can agree that web technologies changed greatly between the births of 2003 and 2013. Office 365 was impossible in 2003 simply based internet speeds. Over the span of a decade, the medium (web) changed quickly and often in surprising ways. To that, add Microsoft’s adventures in rich internet applications (Silverlight) and the emergence of cloud technologies enabled by practically ubiquitous and fast internet connections. Is it surprising that Microsoft has tried to change SharePoint development to account for these things? Is it surprising that some of these were failures?

Just the same, it is possible to migrate solutions originally created for SharePoint Server 2003 to SharePoint Server 2016. Some migrate with little effort and sometimes it is so hard that it isn’t worth it. However, consider that the vast majority of other Web platforms you could buy in 2003 no longer exist as actively developed products. Then, ask yourself: how many of them allow you to take what you did in 2003 and move it with zero effort to their current version? Do you have anything in your current Web development stack that worked in 2003? Are there any that didn’t have some disruptive breaking change between then and now?

Getting $5 of Value from your $10 Purchase

A simple truth in software development is that the less a piece of software depends on other software, the better. This is always offset by the fact that depending on other software makes it faster and cheaper to build systems. Paradoxically the development experience can be much more pleasant even if it takes longer because as a developer you get much more freedom and you don’t have to deal with the quirks or restrictions imposed by the makers of the platform.

Naturally, faster and cheaper pretty much always wins. The users of the software still expect ‘better’, but it is a ‘better’ from their perspective: better at helping themselves do what they want to do. They don’t care how it gets built.

Deliberately tying a solution to a platform makes sense when you can trust the platform to stick around long enough and when the costs of depending on the platform are offset by a sufficiently positive return on investment over the life of the solution. One of those costs is that the implementer will often be more expensive than a generalist because they have to not only understand the set of development technologies and the customer’s requirements, but also understand the design and uses of the platform. In exchange it is expected that the implementers will leverage the platform well enough that the cost of the implementation will still be lower than building a custom solution. If not, it should be true that the total cost of ownership of the system over its life will be lower by using the platform than if it was custom.

If neither of these turns out to be true then the project is a failure on a certain level.

A model where SharePoint becomes a service to custom standalone systems significantly changes SharePoint’s value proposition because it is a deliberate decision to assume the dependency on SharePoint and all of its costs while simultaneously rejecting a big chunk of the features that you can use to offset the costs of ownership. Presumably your solution will still need things, like a user interface, that you could have gotten mostly or even completely from the platform. Perhaps a less expensive web developer could build those for you, but no matter what the hourly rate is, you still built something to use in place of something for which you’ve already paid.

This is a Design Problem

One thing Andrew and I agree on is that a good customization should be as isolated as possible and that a good design should actively address this concern. I think there are times when it is appropriate to treat SharePoint as a service. IQApp Central is a standalone provider hosted solution. It exists outside of SharePoint because we thought the design was most appropriate. On the other hand, add-ins like Instant Practice Manager, the Board of Directors Site, and IQApp Parts are integrated into SharePoint sites and fully integrate the platform. The previous few posts touch on how we isolate AngularJS and Boostrap in IQApp Parts so check those out if you are interested. Keep in mind that this is by no means the only possible way to isolate integrated functionality.

A Note on Patterns and Practices

Andrew says that he thinks Office 365 Dev Patterns and Practices is an example of trying to have your cake and eat it too. I say that it is actually the first time the SharePoint team has made an effort to directly engage and meet customers’ needs with regards to real world scenarios in quite some time. I dare also say that had the program existed the sandbox model would have never been born and the initial forms of the cloud app model would probably have looked very different from what we actually got from Microsoft. I recommend that you check out this post from Vesa Juvonen and decide for yourself if they are serious or not.

This is also a Trust Issue

At the end of day this is also a trust issue. Do you trust Microsoft not to make changes that cost you time and money if you integrate with their platforms?

You shouldn’t! I can guarantee that they will do things to make your life harder at some point in the future.

The same is true of any vendor that offers platforms with a long life span. It doesn’t matter how big they are. Times change and software has to evolve. Sometimes they will make a hash of it. Sometimes the vendor will screw up so badly it will even kill the platform.

If you trust Microsoft to avoid wrecking the bus, then acknowledge the potential bumps in the road and exercise defensive design, but wring every last dollar of benefit you can get out of the platform in the meantime. Moving everything outside the platform is not the way to do it.

If you don’t trust Microsoft to avoid wrecking the bus, that’s OK too, but move on. You are building custom solutions. Surely you can do better and more cheaply than SharePoint as a data and file storage service!

–Doug Ware

Using the SharePoint Client Object Model in AngularJS Apps

A common problem for SharePoint developers new to AngularJS is using the client object model within the context of AngularJS scopes.

The Problem Explained…

If you already understand AngularJS, feel free to skip this part!

Consider a controller that displays the name of the current user.

<div ng-controller="IQAppPart">
  <div ng-if="!!UserName">
     <h1>Hello <span ng-bind="UserName"></span></h1>
  </div>
 </div>
 

If the $scope variable of the IQAppPart has a value for UserName the greeting appears.

The IQAppPart controller function looks like this:

var iqAppPartModule = angular.module(‘iqAppPartModule’, []);
var iqAppPartController = iqAppPartController || {};
iqAppPartController.IQAppPart = function ($scope) {
//Make a request for the user
var ctx = SP.ClientContext.get_current();
var user = ctx.get_web().get_currentUser();
ctx.load(user);

//Send the request to SharePoint
ctx.executeQueryAsync(function () {
    //Set the UserName
    $scope.UserName = user.get_title();
  }, function (error) {
    alert(error.get_message());
  });
};
iqAppPartModule.controller(‘IQAppPart’, [‘$scope’, iqAppPartController.IQAppPart]);

Notice the highlighted line. This sets UserName and you might expect that this would in turn cause AngularJS’s magic data binding to display the greeting, but instead nothing would happen.

The code will run without error and retrieve the UserName, but that’s all. The greeting will not display. The reason for this is hard to see if you are new to AngularJS because the code sets the $scope and the line that does it is inside the controller function!

To understand the problem you must first realize that the call to SharePoint, executeQueryAsync, calls the success handler when it receives the result from SharePoint. The function call is an asynchronous operation that AngularJS knows nothing about.

The second thing you need to understand is that Angular’s model binding expects all operations of interest to start within the confines of an Angular process. When a page that is using Angular starts an Angular app via the presence of the ng-app directive on an HTML element or by calling angular.bootstrap(element), Angular starts listening for events specified element (with the attribute or passed to the bootstrap function) and all of the element’s descendants. So, it knows about clicks and other events. Whenever one happens, it reevaluates the model and then updates the HTML view.

Adding a call to $apply() as shown below fixes the problem. The call to $scope.$apply() tells Angular that something has changed and that it should do its work.

var iqAppPartModule = angular.module('iqAppPartModule', []);
var iqAppPartController = iqAppPartController || {};
iqAppPartController.IQAppPart = function ($scope) {
 //Make a request for the user
 var ctx = SP.ClientContext.get_current();
 var user = ctx.get_web().get_currentUser();
 ctx.load(user);
 //Send the request to SharePoint
 ctx.executeQueryAsync(function () {
   //Set the UserName
   $scope.UserName = user.get_title();
   $scope.$apply();
  }, function (error) {
   alert(error.get_message());
  });
};
iqAppPartModule.controller('IQAppPart', ['$scope', iqAppPartController.IQAppPart]);
 

Calling $apply() in the context of a controller is a big sign that you are doing it wrong!

Instead we need a mechanism that makes ClientContext.executeQueryAsync() work like any other service in AngularJS so that Angular will know when it is time to reevaluate the models and update the views.

The Solution

The solution is a service factory that wraps executeQueryAsync using Angular’s $q
service. $q is a service that helps you run functions asynchronously, and use their return values (or exceptions) when they are done processing.

//Angular service Wrapper for ClientContext executeQuery.
//The $q service makes it easy to wrap SharePoint's context.executeQueryAsync for use with Angular
var module = angular.module('iqPart', [])
 .factory('SharePointService', ['$q', function ($q) {
   var SharePointService = {};
   SharePointService.executeQuery = function (context) {
     var deferred = $q.defer();
     context.executeQueryAsync(deferred.resolve, function (o, args) {
       deferred.reject(args);
     });
     return deferred.promise;
  };
  return SharePointService;
}]);

To use the SharePointService we inject it into the controller and use it instead of ctx.executeQueryAsync as follows.

var iqAppPartModule = angular.module('iqAppPartModule', []);
var iqAppPartController = iqAppPartController || {};

iqAppPartController.IQAppPart = function ($scope, sharePointService) {
  //Make a request for the user
  var ctx = SP.ClientContext.get_current();
  var user = ctx.get_web().get_currentUser();
  ctx.load(user);
 sharePointService.executeQuery(ctx)
   .then(function () {
     $scope.UserName = user.get_title();
   },
   function (error) {
     alert(error.get_message());
 });
};
iqAppPartModule.controller('IQAppPart', ['$scope', 'SharePointService', iqAppPartController.IQAppPart]);
 

The end result is something like:

–Doug Ware

IQParts Design – Isolating AngularJS and Bootstrap

In the previous post I introduced AngularJS 1.4 and Bootstrap 3.3 Web Parts. You can get it using the Free SharePoint Add-Ins page in IQApp Central. This post is about how it all works.

Web Parts and Isolation

My goal was to make the solution as ideal as possible based on the 8 Characteristics of an Ideal SharePoint Customization. To state that a bit more succinctly, the customizations should be isolated but make good use of SharePoint without requiring custom master pages or ASP.Net page customizations. To meet this goals first requires a good container. Users need to be able to add the parts to pages and configure them in the browser. It makes sense therefore to start with one of the stock Web Parts. There are three possible candidates: the Page Viewer Web Part (PVWP), the Content Editor Web Part (CEWP), and the Script Editor Web part. The samples have examples using the PVWP and CEWP.

In either case we want to contain the custom functionality inside an iframe element for each part. The main difference between the two parts is that the CEWP requires an extra piece. The PVWP is therefore a bit easier. In terms of end user experience we weren’t able to tell a difference, but we included both part containers because theoretically the CEWP version is more flexible – you can customize the extra HTML file and the iframe.

Seriously? An iframe?

In the context of SharePoint 2013 the humble iframe has gotten a bad reputation because it is the basis of the App Part. The problem is that the App Part design requires the contents of the iframe to be in a different domain. This is done to prevent cross-site exploits and it works because by default a frame from an origin other than the parent page’s domain is isolated and can’t read the parent page or even the parent page’s URL. Many of the frustrations developers have with the app model stem from this. It makes everything far more complicated.

In this case we are using an iframe simply to load a page from the same site where the pages which contain the Web Parts are loaded. Because the parent Wiki or Web Part page is served from the same domain as the part container, the part can work with the parent window to resize itself, detect that the page is in edit mode, and read the parent’s URL and query string. It can also, if necessary, communicate with other IQParts on the same page. At the same time the frame gives us isolation so that Bootstrap and AngularJS can’t break anything outside the iframe.

SPABody.aspx

The iframe loads a file named SPABody.aspx which is the actual container for the app’s functionality. It loads the SharePoint object model, AngularJS, Bootstrap, and Angular-UI. Other dependencies are injected at runtime based on each app’s specific configuration.

Of special interest is this line:

<div
ng-include=”RootTemplate + ‘?m=’ + Modified”></div>

It uses Angular’s ng-include directive to load a partial html template based on the value of RootTemplate which is set during initialization.

Configurations.js and IQPart.js

SPABody.aspx directly contains two custom script files. The first, configurations.js, is generated on the fly when users configure the parts on a page. Configurations.js is an optimization to prevent the need to round trip to the SharePoint server for configuration data – more on this later. The second script, iqpart.js, implements the rest if the wrapper’s functionality.

IQPart.js is fairly long and so I am not including its source here. You can get it by installing the sample.

How the AngularJS Apps Work

Everything starts when a user adds the container Web Part to a page.

The Web Part points to SPABody.aspx which loads iqpart.js.

When iqpart.js loads, it looks for a configuration for the part. If it doesn’t find one it sets RootTemplate to default.html which is a partial located in the same folder as SPABody.aspx. If the page is in design mode, the part looks like this…

Otherwise it looks like this…

The selection dropdown displays all of the available apps. These are loaded by iterating the folders in /IQAppCore/SPAs.

If you select Create new AngularJS app… the part presents a form allowing you to name the app and give it a description.

Once you select Create New App, iqpart.js creates a new folder, in this case /IQPart/SPAs/My New Demo App, and copies the starter template files into the new folder. The default files are:

  • App.html – The RootTemplate of the new app
  • App.js – The AngularJS module and controller for the new app
  • App.css – The app’s custom styles
  • Config.html – The app’s configuration page
  • defaultConfig.js – The app’s default settings

The generated file looks like this:

//This is the default configuration for this app part
var p = window.iqPart; if (!!p && !!p.SetNewConfiguration) { 
    p.SetNewConfiguration( 
        {        
            //Add your custom properties here
            "SelectedDemo": "timer", 
            //Or overide defaults
            "Name": "My New Demo App", 
            "Description": "A nice description",
            "RootTemplate": "app.html",
            "Scripts": [ 
                "app.js" 
            ],
            "Styles": [
                "app.css"
            ],
            "Modules": [
                "iqAppPartModule"
            ]
        });
}

Based on the configuration, iqpart.js will load additional scripts and styles, and you can override the default module name. If you have installed the sample, compare the defaultConfig.js files for the six included samples.

The default Config.html looks like this…

You can add your own configuration values by altering this form. In this case the only setting is the demo mode and it is set to display a greeting. The other option is to display a timer. The html template is app.html and the script is app.js.

The greeting demo illustrates the use of SharePoint JSOM and makes use of a service wrapper that makes it easy to use JSOM with AngularJS.

Getting Started with AngularJS Samples

Three of the included samples come from the homepage of http://angularjs.org. They are Getting Started, Add Some Control, and Create Components. Each has a video!

Join us on Slack

Want to talk about this sample and the rest of the IQApp Central awesomeness? If you register, we will invite you to join us on our Slack network.

–Doug Ware

IQParts – Cloud App Compatible Web Parts using AngularJS and Bootstrap

We are in the process of releasing three free SharePoint Add-ins from IQApp Central: Absence and Vacation Request Management Site, Board of Directors Site, and AngularJS 1.4 and Bootstrap 3.3 Web Parts. We’ll release all three as side-loaded apps over the next couple weeks for host webs and the first two as SharePoint hosted apps will be available via the Office store. Until then, you can get all three using Free SharePoint Add-Ins page in IQApp Central.

Today I am pleased to introduce AngularJS 1.4 and Bootstrap 3.3 Web Parts. This is a sample created using IQApp Central​. It is a framework that allows for user configurable Web Parts built using SharePopint, AngularJS 1.4 and Bootstrap 3​. ​This sample contains two Web Parts, six sample apps, an extensible configuration system, a template to help you get started with your own apps, and some handy functions to make integrating with SharePoint pages and services easy.

This sample started as an exercise to attempt an ideal design based on the 8 Characteristics of an Ideal SharePoint Customization. Integrating AngularJS and Bootstrap with SharePoint while trying to maximize the 8 ideals is a great challenge because SharePoint and AngularJS are both very assertive, demanding frameworks that want total control over a page and Bootstrap wants to completely own the base styles.

For example, here is a SharePoint page.

And here is the same page with Bootstrap 3’s CSS loaded.

Most projects that use Bootstrap start with a custom master page and end with a complete theme. Naturally this is not an option when you are creating components that, like Web Parts, are expected to work on any site.

Here is one of the sample pages included in AngularJS 1.4 and Bootstrap 3.3 Web Parts. It contains three of the sample apps and has a theme applied. Note how the parts do not break the containing page or the site’s style.

Configurability

There are a few projects out there that have tackled the configurable Web Part problem including this very good one by Rachid Bouzalmat. This approach works, but it is less than ideal on a couple of counts (based on the 8 Characteristics of an Ideal SharePoint Customization). Specifically it uses jQuery to target particular elements in a SharePoint page. It also depends on the ability to hijack SharePoint’s JavaScript. In the interest of full disclosure, we have code that does both of those things for different reasons. I am just as guilty, just not in the case of this sample!

I will write more about how we implemented our Web Part containers and the configuration system in a future post. In the meantime you can see for yourself how it works by installing the sample. Until then here is a shot of the sample page in design mode.

–Doug Ware