Office 365 addins as microservices on Docker containers


Office 365 Addins on Docker

This example shows how to run office 365 addins as microservices on Docker containers

https://github.com/spbreed/O365OnDocker

watch this video to see this in action

Below sections would be covered in this sample

  1. Why Docker?
  2. Prerequisites
  3. Configure Docker
  4. Docker Components
  5. Docker Commands
  6. Build NodeJS Base Image
  7. Build Office 365 NodeJS Microservice
  8. Dockerize Office365 Microservice
  9. Publish Microservice to Azure Docker Container
  10. How to run this sample

1. Why Docker?

  • Docker is an exciting new technology to build platform agnostic light weight apps/micro services/containers which can be provisioned, deployed, scaled faster than traditional VM’s.
  • Building Cloud hosted/provider hosted SharePoint/Office365 addins requires additional infrastructure to the mix.
  • Docker’s X-Plat CLI tools to provide continous integration and delivery thus making DevOps relatively simpler.
    For more details read docker docs

2. Prerequisites

  1. Windows 7 or Above
  2. Office 365 subscription
  3. Azure subscription
  4. Visual Studio Code

3. Configure Docker

  1. Install docker tool kit from docker docs
  2. Run docker quick start terminal
  3. To run this sample straightaway skip to “10. How to run this sample”.

4. Docker Components

  1. Docker Images > Blueprints of our application
  2. Docker Container > Created from docker images and are real instances of our application
  3. Docker Daemon > Building, running and distributing Docker containers
  4. Docker Client > Run on our local machine and connect to the daemon
  5. Docker Hub > A registry of docker images

5. Docker Commands

  1. $docker build
  2. $docker run
  3. $docker search
  4. $docker ps
  5. $docker images
  6. $docker rmi
  7. $docker pull
  8. $docker push
  9. $docker-machine env
  10. $docker-machine create
  11. $docker attach

6. Build NodeJS Base Image

FROM ubuntu:latest
RUN apt-get update
RUN apt-get install -y nodejs nodejs-legacy npm
RUN apt-get clean

7. Build Office 365 NodeJS Microservice

Run the sample Office 365 Add in from your local machine following this article

8. Dockerize Office365 addin

  • First install the required packages from package.json
COPY ./package.json src/
RUN cd src && npm install
  • Then copy all the source code
COPY . /src
  • Set working directory for docker daemon
WORKDIR src/
  • Set default comment on start
CMD ["npm","start"]
  • Now build the Docker Image and Run it
docker build -t o365addin-docker:0.1 .
docker run -d -p 80:3000 o365addin-docker:0.1
  • Change the AppID and Redirection URL’s in Azure and authHelper.js

  • Test the app in browser

9. Publish Microservice to Azure

1) Create SSL certs using Open SSL

openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout o365-docker.pem -out o365-docker.pem
openssl x509 -inform pem -in o365-docker.pem -outform der -out o365-docker.cer
openssl pkcs12 -export -out o365-docker.pfx -in o365-docker.pem -name "o365-docker Certificate"

2) Upload o365-docker.pem to Azure -> Settings -> Management Certificates -> Upload

3) Now Create a docker Microservice in Azure

docker-machine create -d azure --azure-subscription-id="d48ccdca-d4ab-4579-89fa-ed113033bf74" --azure-subscription-cert="o365-docker.pem" --azure-location="East US" o365ondocker

4) Connect to Azure Docker machine

eval "$(C:/Program\ Files/Docker\ Toolbox/docker-machine.exe env o365ondocker)"

5) Change the AppID and Redirection URL’s in Azure and authHelper.js

6) Build and Run the app

docker build -t o365addin-docker:0.1 .
docker run -d -p 80:3000 o365addin-docker:0.1

7) Test the app in browser

10. How to run this sample

1) Open Docker quick start terminal
2) Clone this repo

git clone https://github.com/spbreed/O365OnDocker.git

3) Update Office 365 App permissions and authhelper.js with Docker IP

docker-machine ip default

4) Build the docker image

docker build -t o365addin-docker:0.1 .

5) Run the docker container

docker run -d -p 80:3000 o365addin-docker:0.1
Advertisements

AutoSPInstaller with #SP2016 on #Win2016 and #SQL2016


Since the release AutoSPInstaller by Brain Lalancette in 2010 , I am an ardent fan of this tool and used it in every other SharePoint deployment.

Not surprisingly AutoSPInstaller for SharePoint 2016 is out immediately after few days of #SP2016 Preview release.

Recently AutoSPinstaller online is release as well to generate the farm configuration file to run this tool.

For more details refer  https://autospinstaller.com/Guide

Recently I had a chance to install SP2016 on Win2016 and SQL 2016. AutoSpInstaller worked fine without any glitch and I was able to configure a single server farm in 4-5 hrs on Azure.

Here are the steps:

  1. Launch a VM using Win Server 2016 Technical preview 3 base image or install it on a Local VM2016_image_select
  2. Provision E:\ and F:\ for SQL and Logs
  3. Join the server to a domain
  4. Fully functional SharePoint install requires atleast 9 service accounts. Below PowerShell script can be used to automate Service account creation and to configure “No password expiry” policies. Update the CSV file with required values: Create-ADUsers.ps1
  5. Add replicating directory changes permission to spprofilesync account https://technet.microsoft.com/en-us/library/Hh296982.aspx
  6. Though SharePoint adds required firewall ports during setup, I used the below scripts to add required firewall ports in advance
    1. Create-FWRulesDB.ps1
    2. Create-FWRulesWFE.ps1
  7. Download and Install SQL server 2016 preview from https://www.microsoft.com/en-us/evalcenter/evaluate-sql-server-2016. Use SQLService accounts created in step 3 while configuring SQL services
  8. Pre configure app domain using http://sharepointchick.com/archive/2012/07/29/setting-up-your-app-domain-for-sharepoint-2013.aspx
  9. Download AutoSPSourcebuilder from http://autospsourcebuilder.codeplex.com/ and unzip in the same drive
  10. Download AutoSPInstaller from http://autospinstaller.codeplex.com/ and unzip in the same drive 
  11. Download #SP2016 preview from http://www.microsoft.com/en-us/download/details.aspx?id=48712 and mount it as 

    MOUNT-DISKIMAGE C:\ISO\SharePoint Server 2016 IT Preview.ISO

  12. Now navigate to AutoSPSourceBuilder  and run PS F:\AutoSPSourceBuilder> .\AutoSPSourceBuilder.ps1 -GetPrerequisites:$true  -Destination “F:\AutoSPInstaller\SP\2016”   to create SlipStreamed version of #SP2016

    AutoSourceBuilder

  13. Now prepare AutoSPInstallerInput.xml for SharePoint 2016. Its highly recommended use https://autospinstaller.com/  to generate this config today. But as of today (09/03/2016) online    tool to generate config file for SP2016 is not supported. Only notable difference wrt to AutoSPInstaller between #SP2013 and #SP2016 is the introduction MinRoles to simplify the deployment and scaling. For more details refer http://blogs.technet.com/b/wbaer/archive/2015/05/12/what-s-new-in-sharepoint-server-2016-installation-and-deployment.aspx
  14. Select <SingleServerFarm Provision=”true” /> for single server farm setup. Attached is the sample Config file for SP2016 for your reference. AutoSpInstallerInput.xml minroles
  15. Now run the .\AutoSPInstallerLaunch.bat. Installation will be a breeze.

portal

TEZURE – Cost effective IOT apps using Javascript, Tessel & Azure


TEZURE

Cost effective IOT device using Javascript, Tessel & Azure

  • With the recent advancements to embedded hardware technologies, micro-controller product lines like Tessel, Espruino, RasberryPI etc where able to build compilers to breakdown Programs written in most popular programming languages in to Javascript, Python to Assembly code.

  • With Cloud providers such as Azure, AWS etc allow easy access to Queue and Storage services in a secured way, Industry experts predict that by 2020 the Internet of things (IoT) network will reach ~200 billion connected devices.

  • This blog post explains how to create a IOT device using Javascript, Tessel and Azure.

Tezure-SpyCam Demo

GitHub Site

Internet Of Things (IOT)

The Internet of Things (IoT) is the interconnection of uniquely identifiable embedded computing devices within the existing Internet infrastructure

Every Industry is getting Smarter

  • Smart Logistics
  • Smart Home
  • Smart Industries
  • Smart Healthcare
  • Smart Entertainment

With number of internet connected devices is exploding, there is a need for enabling and controlling services remotely.

Why IOT

  • Enabling services remotely
  • More targeted services
  • Data driven insights
  • Cost efficient

Tezure – SpyCam

  • Mobile controlled Surveillance Camera
    Scenario

Complexities

  • Design & Build
  • C, C++ for Sensors/Devices
  • C#, JAVA for cloud services
  • C#, Java, Obj C for Mobile devices
  • Connectivity (IP & Non IP devices)
  • Security – Identity and Authorization
  • Scalability

Keep it simple

  • Cost efficient
  • End to End solutions using pure Javascript
  • Tessel based devices/sensors
  • X platform mobile apps using Cordova/PhoneGap

  • REST based access to Azure Service bus/Azure Blobs

Hello Tessel!

Architecture
– Tessel is a microcontroller that runs JavaScript.
– It’s NodeJS-compatible and ships with Wifi built in.
– Its easier than ever make physical devices that connect to the web.
– Bridges the gap between Embedded devices and Web development

What Azure Offers

  • Azure Service bus
  • Queues, Topics, relays for messaging
  • Mobile services for push notifications and data tables
  • Azure store blobs
  • Images and Video storage
  • SAS (Shared Access Token) based authentication via REST
  • Supports Async access using NodeJS/Javascript

What PhoneGap Offers

  • PhoneGap is a free and open source framework that allows you to create X-Plat mobile apps using Web technologies
  • Mobile Apps can be created using HTML, Javascript and CSS
  • PhoneGap Build takes the pain out of compiling PhoneGap apps. Get app-store ready apps without the headache of maintaining native SDKs.

Tezure SpyCam – Architecture

Architecture

– Tessel

  • Tessel setup consists of Tessel Microcontroller and Camera module
  • Nodejs packages can be installed inside the tessel devices
  • Current set up consists of tesselPollingService() function which continously checks for new message on Azure queue
  • On new message, Camera module takes a picture and uploads to Azure blob storage
  • ‘Tesselate’ NPM module is used to load the Camera Module functions.
  • ‘Async’ NPM module is used to process the Polling cycles asynchronously
require('tesselate')(['camera-vc0706'], function (tessel, modules) {
console.log("Executed action 2 : After Camera Load : cycle no : " + count );
async.auto({
listen_messages: function (callback) {
var options = {...

Source Code

– Azure service bus

  • Azure queue receives messages from the Mobile applications and authenticated via SAS token
  • Azure Blob storage receives Images from tessel devices and authenticated via SAS
  • CORS rules can be added to Azure storage to enable X-domain requests

– PhoneGap App

  • Sends a surveillance request message with Device ID and time stamp
  • Polls the Azure Storage to retreive image with DeviceID and time stamp
  • Built with end to end javascript
    Source Code

PreRequisites

Few Gotcha’s

Azure hosted SharePoint apps using AngularJS and WebAPI – Part 3


This is final post of a three part series on exploring Azure hosted SharePoint apps using AngularJS and WebAPI.

Part 1: Why Cloud and AppModel?

Part 2: SQLAzure data via WebAPI:

Part 3: Azure hosted apps using AngularJS and WebAPI

Why AngularJS:

 Traditionally managed server-side programming used to develop enterprise apps. But now this pattern is changing in the enterprise application development industry.  It’s a change away from logic on the server side, and towards logic on the client side. To address these complex business logic Javascript should evolve from just a language to make DOM manipulations to powerful client side MVC/MVVM framework. AngularJS framework makes this shift at ease.

AngularVSKnckout

 

 

 

There are also few other frameworks on the same course but AngularJS is a clear leader owing to these facts:

1)       Dependency injection:

This is huge and my personal favorite. Using this, custom modules can be injected just like adding assemblies on the server side code. This makes life little easier design MVC/MVVM based projects with separation of concern, modularity etc. An Analogy to server side code is represented below

Step38_ServerClient

 

 

2)      HTML templating:

Over the past few years, Single Page App’s (SPA’s) are gaining of a lot of traction from front end developers and end users. HTML templating feature in Angular makes it possible to easily switch the HTML in SPA’s.

 3)      Two way binding:

Fellow Silverlight developers can understand the complexity of two-way binding using propertychange events back in the old days. But AngularJS databinding makes this right OOB

 4)      Community support:

Google continues to develop and maintain the library. Large community of developers has embraced the framework so ample support is available on Stackoverflow and AngularJS official site.

5)      Advance error handling and logging features

Why AngularJS on Provider hosted App:

 Instead of using server side code on Provider hosted app, client side code is used for a sole reason to utilize AngularJS framework. Some of the advantages include

  •  Single Page App (SPA)
  • Clean URL for easy navigation
  • Responsive design
  • No server side code
  • Scalable for further enhancements

Future enhancements may include:

1)       Adding Chrome controls to give SharePoint look and feel

2)      Authentication for WebAPI

3)      Functions to delete/update O365 and WebApi Data. etc

 

Design of this app is based on Hot Towel app from John Papa and the pluralsight course from Andrew Connell.

It requires a bit of learning to understand the AngularJS. Go through these resources for deep understanding

http://pluralsight.com/training/courses/TableOfContents?courseName=building-sharepoint-apps-spa-angularjs

http://pluralsight.com/training/courses/TableOfContents?courseName=build-apps-angular-breeze

http://www.johnpapa.net/hot-towel-angular/

SPAngular APP:

1)       Create a new provider host app project in VS2013

2)      New Project -> App for SharePoint -> Provider Hosted App -> ASP.NET Web Forms Application -> Use Windows Azure Access Control Service ->finish

Step39_ProviderHosted

3)      Now click the web project -> Manage NuGet Packages

Nugets

4)      Search “hot towel” and install HotTowel.Angular.

Nugets_HotTowel

 

5)      Main benefit of using this project template is all the heavy lifting of implementing MVC project structure, logging, exception handling, angularJS, configuration comes OOB. This makes this bootstrap project easily extensible for custom functionalities.

Step25_App3

6)      By default App project creates Query String tokens to store URL’s of Appweb , hostweb etc for reference in the future.

Step35_AppXML

7)      AngularJS navigation is based on the URL manipulations. Its little hard to implement the navigation with these long URL’s. So the idea is to use a applauncherpage to store the Querystring values to cookies for future use and redirect to the main page with clean URL.

8)      Create applauncher.html and applauncher.js. Create an empty controller and all the JS references from index.html.


<!DOCTYPEhtml><!--// ** Step 1: Add AppLauncher:  **//-->

<htmldata-ng-app="app">

<head>

<title>App Launcher</title>

</head>

<bodydata-ng-controller="applauncher as vm">

 

<!--// ** Step 2: Add Angular libs:  **//-->

<!-- Vendor Scripts -->

<scriptsrc="../scripts/jquery-2.1.1.js"></script>

<scriptsrc="../Scripts/jquery.extensions.js"></script>

<scriptsrc="../scripts/jquery.cookie.js"></script>

<scriptsrc="../scripts/angular.js"></script>

<scriptsrc="../scripts/angular-animate.js"></script>

<scriptsrc="../scripts/angular-resource.js"></script>

<scriptsrc="../scripts/angular-route.js"></script>

<scriptsrc="../scripts/angular-sanitize.js"></script>

<scriptsrc="../scripts/bootstrap.js"></script>

<scriptsrc="../scripts/toastr.js"></script>

<scriptsrc="../scripts/moment.js"></script>

<scriptsrc="../scripts/ui-bootstrap-tpls-0.10.0.js"></script>

<scriptsrc="../scripts/spin.js"></script>

 

<!-- Bootstrapping -->

<scriptsrc="../app/app.js"></script>

<scriptsrc="../app/config.js"></script>

<scriptsrc="../app/config.exceptionHandler.js"></script>

<scriptsrc="../app/config.route.js"></script>

 

<!-- common Modules -->

<scriptsrc="../app/common/common.js"></script>

<scriptsrc="../app/common/logger.js"></script>

<scriptsrc="../app/common/spinner.js"></script>

 

<!-- common.bootstrap Modules -->

<scriptsrc="../app/common/bootstrap/bootstrap.dialog.js"></script>

 

<!-- app -->

<scriptsrc="../app/admin/admin.js"></script>

<scriptsrc="../app/dashboard/dashboard.js"></script>

<scriptsrc="../app/layout/shell.js"></script>

<scriptsrc="../app/layout/sidebar.js"></script>

 

<!--// ** Step 5: Create Add references **// -->

<!-- app Services -->

<scriptsrc="../app/applauncher.js"></script>

<scriptsrc="../app/services/spappcontext.js"></script>

 

</body>

</html>

 

 

9)      In the applauncher.js call spappcontext angular service.


// ** Step 3: Add AppLauncher JS:  **//

(function(){

'use strict';

var controllerId ='applauncher';

var app = angular.module('app');

app.controller(controllerId,['common','spappcontext', applauncher]);

 

function applauncher(common, spappcontext){

var getLogFn = common.logger.getLogFn;

var log = getLogFn(controllerId);

activate();

function activate(){

common.activateController([], controllerId)

.then(function(){ log('Activated App Launcher View');});

}

 

}

})();

10)   Create SPappcontext.js and create createSPAppContext()and loadSPAppContext() functions to read the query string and store it to cookies. This also redirects to \index.html, a Single page app.


(function(){

'use strict';

var serviceId ='spappcontext';

var app = angular.module('app');

app.service(serviceId,['common','$window','$location', spappcontext]);

function spappcontext(common, $window, $location){

var getLogFn = common.logger.getLogFn;

var log = getLogFn(serviceId);

var service =this;

var spweb ={

providerUrl:'',

SPAppWebUrl:'',

SPHostUrl:''

};

service.hostWeb = spweb;

init();

function init(){

var test = jQuery.getQueryStringValue('SPHostUrl');

if(decodeURIComponent(jQuery.getQueryStringValue('SPHostUrl'))==="undefined")

{

loadSPAppContext();

}

else

{

createSPAppContext();

}

}

function loadSPAppContext(){

log('loading spcontext cookie');

service.hostWeb.providerUrl = $.cookie("ProviderUrl");

service.hostWeb.SPAppWebUrl = $.cookie("SPAppWebUrl");

service.hostWeb.SPHostUrl = $.cookie("SPHostUrl");

}

function createSPAppContext(){

log('writing spcontext cookie');

var ProviderUrl = $window.location.protocol +"//"+ $window.location.host;

$.cookie("ProviderUrl", ProviderUrl,{ path:'/'});

var appWebUrl = decodeURIComponent(jQuery.getQueryStringValue('SPAppWebUrl'));

$.cookie("SPAppWebUrl", appWebUrl,{ path:'/'});

var url = decodeURIComponent(jQuery.getQueryStringValue('SPHostUrl'));

$.cookie('SPHostUrl', url,{ path:'/'});

$window.location.href = ProviderUrl +"/index.html";

}

}

})();

11)    Now add host web SP JS libraries to index.html to for make JSOM calls against host web.


<!--// ** Step 7: Add SharePoint libs for JSOM calls **// -->

<!--SharePoint-->

<scriptsrc="https://spbreed.sharepoint.com/sites/dev/_layouts/15/SP.RunTime.js"></script>

<scriptsrc="https://spbreed.sharepoint.com/sites/dev/_layouts/15/SP.js"></script>

<scriptsrc="https://spbreed.sharepoint.com/sites/dev/_layouts/15/SP.RequestExecutor.js"></script>

Now add the following code to web.config remove the static file issue on described here http://rainerat.spirit.de/2012/09/03/SharePoint-2013-App-HTTP-Error-405.0/

<!--// ** Step: 8: To Resolve IIS Static file issue**//-->

<system.webServer>

<modulesrunAllManagedModulesForAllRequests="true"/>

<handlers>

<addname="AspNetStaticFileHandler" path="*" verb="*" type="System.Web.StaticFileHandler" />

<addname="StaticHTML" path="*.html" verb="GET,HEAD,POST,DEBUG,TRACE" modules="StaticFileModule" resourceType="File" requireAccess="Read" />

</handlers>

</system.webServer>

[/xml]

12)   Now use JSOM to call host web and REST calls to WebAPI. $q.defer() objects are used to  pass promise to the calling function. This enables clients to complete the DOM structure without waiting for results.( Host web contains a demo contact list with title “DemoCustomer”
<pre>

// ** Step 6: Create Datacontext Service **//

(function(){

'use strict';

&nbsp;

var serviceId ='datacontext';

angular.module('app').factory(serviceId,['$rootScope','$resource','spappcontext','common', datacontext]);

&nbsp;

function datacontext($rootScope,$resource, spappcontext,common){

var $q = common.$q;

&nbsp;

&nbsp;

var service ={

getPeople: getPeople,

getMessageCount: getMessageCount,

getUserName: getUserName,

getCustomers: getCustomers,

getSPContacts: getSPContacts

};

&nbsp;

return service;

&nbsp;

function getCustomers(){

&nbsp;

var dfd = $q.defer();

var webApi = $resource('http://customerwebapi.cloudapp.net/api/Customer/:Id',{ Id:"@Id"},{ update:{ method:'PUT'}});

//   var webApi = $resource('http://localhost/AppWeb/api/Customer/:Id', { Id: "@Id" }, { update: { method: 'PUT' } });

webApi.query(function(data){

var customers = data;

customers.splice(4,847)

dfd.resolve(customers);

},function(error){

console.log(error);

dfd.reject(error);

});

return dfd.promise;

}

&nbsp;

function getUserName(){

&nbsp;

var dfd = $q.defer();

&nbsp;

// Standard function to get hostweb

var ctx =new SP.ClientContext(spappcontext.hostWeb.SPAppWebUrl);

var factory =new SP.ProxyWebRequestExecutorFactory(spappcontext.hostWeb.SPAppWebUrl);

ctx.set_webRequestExecutorFactory(factory);

var hostWebctx =new SP.AppContextSite(ctx, spappcontext.hostWeb.SPHostUrl);

&nbsp;

var appWeb = ctx.get_web();

var hostWeb = hostWebctx.get_web();

var currentAppWebUser = appWeb.get_currentUser();

var currentHostWebUser = hostWeb.get_currentUser();

&nbsp;

ctx.load(appWeb);

ctx.load(hostWeb);

ctx.load(currentAppWebUser);

ctx.load(currentHostWebUser);

&nbsp;

ctx.executeQueryAsync(function(){

var userName = currentAppWebUser.get_title();

dfd.resolve(userName);

},function(sender, args){

console.log(args.get_message()+" "+ args.get_stackTrace());

dfd.reject(args.get_message());

});

&nbsp;

return dfd.promise;

}

&nbsp;

function getSPContacts()

{

var dfd = $q.defer();

// Standard function to get hostweb

var ctx =new SP.ClientContext(spappcontext.hostWeb.SPAppWebUrl);

var factory =new SP.ProxyWebRequestExecutorFactory(spappcontext.hostWeb.SPAppWebUrl);

ctx.set_webRequestExecutorFactory(factory);

var hostWebctx =new SP.AppContextSite(ctx, spappcontext.hostWeb.SPHostUrl);

&nbsp;

var appWeb = ctx.get_web();

var hostWeb = hostWebctx.get_web();

&nbsp;

var ContactList = hostWeb.get_lists().getByTitle('DemoCustomer');

var contactListItems = ContactList.getItems(SP.CamlQuery.createAllItemsQuery());

ctx.load(ContactList);

ctx.load(contactListItems);

ctx.executeQueryAsync(function(){

var enumerator = contactListItems.getEnumerator();

var SPContacts =[];

while(enumerator.moveNext()){

var currentItem = enumerator.get_current();

SPContacts.push({"FirstName": currentItem.get_item('FirstName'),"LastName": currentItem.get_item('Title')});

}

var SPContactsObj = SPContacts;

&nbsp;

dfd.resolve(SPContactsObj);

},function(sender, args){

console.log(args.get_message()+" "+ args.get_stackTrace());

dfd.reject(args.get_message());

});

return dfd.promise;

}

}

})();

13)   Now modify dashboard.js to call data service functions defined above and add spinner while waiting for results.


(function(){

'use strict';

var controllerId ='dashboard';

angular.module('app').controller(controllerId,['common','datacontext', dashboard]);

&nbsp;

function dashboard(common, datacontext){

var getLogFn = common.logger.getLogFn;

var log = getLogFn(controllerId);

&nbsp;

var vm =this;

vm.news ={

title:'Hot Towel Angular',

description:'Hot Towel Angular is a SPA template for Angular developers.'

};

vm.messageCount =0;

vm.people =[];

vm.SPContacts =[];

vm.Customers =[];

vm.title ='Dashboard';

vm.busyMessage ='Please wait ...';

vm.isBusy =true;

vm.spinnerOptions ={

radius:40,

lines:7,

length:0,

width:30,

speed:1.7,

corners:1.0,

trail:100,

color:'#F58A00'

};

&nbsp;

activate();

&nbsp;

function activate(){

var promises =[getMessageCount(), getPeople(), getSPContacts(), getCustomers()];

common.activateController(promises, controllerId)

.then(function(){ log('Activated Dashboard View');});

}

&nbsp;

function getCustomers(){

toggleSpinner(true);

return datacontext.getCustomers().then(function(data){

toggleSpinner(false);

return vm.Customers = data;

});

}

&nbsp;

function getMessageCount(){

return datacontext.getMessageCount().then(function(data){

return vm.messageCount = data;

});

}

&nbsp;

function getPeople(){

return datacontext.getPeople().then(function(data){

return vm.people = data;

});

&nbsp;

}

&nbsp;

function getSPContacts(){

&nbsp;

return datacontext.getSPContacts().then(function(data){

return vm.SPContacts = data;

});

&nbsp;

}

&nbsp;

function toggleSpinner(on){ vm.isBusy = on;}

}

})();

14)   Now add remote endpoint http://customerwebapi.cloudapp.net to the appmanifest.xml

Step36_AppXML_Remoteendpoint

15)   Now navigate to /_layouts/15/appregnew.aspx to generate client Id and client secret. Note down these values.

Step28_AppregNew

16)   Now right click the web project and select publish to select a new publishing profile

Step29_PublishingProfile

17)   Seed the values of the ClientID and Client Secret noted earlier.

Step30_PublishingProfile

18)   Now select the created profile and deploy to Azure Website.

Step31_PublishingProfile

19)   Add a site name and click create

Step32_PublishingProfile

20)   Keep the default settings and click publish.

Step33_PublishingProfile

21)    Now package the app and upload the app to the Office 365 site.

Step34_PublishingProfile

22)   Now clicking the app will navigate to the provider hosted app with displays data from both Office 365 and WebAPI.

Step2_Responsive

This project is hosted in codeplex for download: https://spangular.codeplex.com/ 

Azure hosted SharePoint apps using AngularJS and WebAPI – Part 2


This is second post of a three part series on exploring Azure hosted SharePoint apps using AngularJS and WebAPI.

Part 1: Why Cloud and AppModel?

Part 2: SQLAzure data via WebAPI:

Part 3: Azure hosted apps using AngularJS and WebAPI

SQLAzure data via WebAPI:

This is the continuation of this post on creating Azure hosted enterprise apps using AngularJS and WebAPI.

WebAPI is a framework for building RESTful applications which enables client browsers to tap in to database using HTTP  GET, POST, DELETE requests.  This involves following steps:

Note: Following steps require valid Azure subscription. Microsoft offers free credits for MSDN subscribers. http://azure.microsoft.com/en-us/pricing/member-offers/msdn-benefits-details/

1)       Create a SQL server instance in Azure management portal https://manage.windowsazure.com -> SQL Databases -> New

Step4_SQLAzure1

 

2)      Create SQL Database. I am using AdventureWorksLT2012 database for this demoapp. This is downloaded from http://msftdbprodsamples.codeplex.com/releases/view/55330 . After restoring this app on local instance, create a database in SQLAzure with the same name.

Step5_SQLAzure2

3)      Once the database is created, the properties can be accessed by clicking through it.

Step6_SQLAzure3

4)      Now migrate the SQL DB from local instance to SQL azure using SQLAzure Migration Wizard. http://sqlazuremw.codeplex.com/

Step7_SQLAzure4

5)      SQLAzure supports only a subset of SQL features. Some of the limitations are listed here

http://msdn.microsoft.com/en-us/library/azure/ff394115.aspx . XML Schema collections are not supported so uncheck it.

Step8_SQLAzure5

6)      Now click next to generate SQL script to create database. Script displays non supported items in RED.

Fix these items and re-generate the script until all these errors are cleared. Follow this article to resolve some of the most common errors http://oakleafblog.blogspot.com/2010/01/using-sql-azure-migration-wizard-v313.html

Step9_SQLAzure6

7)      Now run this script on SQLAzure instance by keying the connection details of Azure DB created earlier

Step10_SQLAzure7

8)      Now connect to SQLAzure using SSMS

Step3_FinalDatabase

9)      Now to expose the database via WebAPI.

To do this install Azure SDK by following this link

http://msdn.microsoft.com/en-us/library/ff687127.aspx

Install Entity Framework Powertools to convert SQL objects to .net entities

http://visualstudiogallery.msdn.microsoft.com/72a60b14-1581-4b9b-89f2-846072eff19d

10)   Create new “Windows Azure Cloud Service” project. This creates a project with web role. Refer “Cloud Services” section in the article http://azure.microsoft.com/en-us/documentation/articles/fundamentals-introduction-to-azure/ to understand more on this. Basically this project creates a VM and IIS in Azure to host WebAPI web services on deployment.

Step11_WebApi1

 

11)    Now Right Click WebRole project -> Entity framework -> Reverse Engineer Code First and connect to SQLAzure DB created earlier. This will generate all the required entities.

Step12_WebApi2

12)   This generates table, table mapping and database context classes.

Step13_WebApi3

13)   Now create a controller of customer class using Scaffolding. Scaffold templates are used to generate code for basic CRUD operations for WebApi project against database using DB entity objects generated earlier.

 

Step14_WebApi4

Step15_WebApi5

 

Step16_WebApi6

 

14)   Add  navigate to App Start -> WebAPIConfig.cs and add the following code highlighted under step 2 to enable JSON


public static void Register(HttpConfiguration config)

{

// ** Step: 2: Enable JSON **//

// Web API configuration and services

var json = config.Formatters.JsonFormatter;

json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;

config.Formatters.Remove(config.Formatters.XmlFormatter);

// Web API routes

config.MapHttpAttributeRoutes();

&nbsp;

config.Routes.MapHttpRoute(

name: "DefaultApi",

routeTemplate: "api/{controller}/{id}",

defaults: new { id =RouteParameter.Optional }

);

// ** Step: 3: Enable CORS **//

&nbsp;

var cors =newEnableCorsAttribute("*", "*", "GET, POST, OPTIONS");

config.EnableCors(cors);

}

}

15)   Now Right Click WebRole Project -> Manage Nuget Packages ->Type Cors and install the WebAPI 2.1 cross origin support. This API is used to enable cross origin services for the WebAPI.

Step23_App1

Nugets_Cors

16)   Now add the code to highlighted under “step 3” enable CORS

17)   This will generate required WebApi controller to service Read, Delete and update operations. Right click WebApi project and publish.

Step17_WebApi7
Step18_WebApi8

18)   This will take few minutes to spin up a VM and publish these resources in Azure. Once the deployment is complete, data can be accessed from WebApi service.

Step19_WebApi9

19)   Now click the new cloud service created via Azure management portal

Step20_WebApi10

20)   Navigate to “Instances” tag and click “Connect” button to remote into VM

Step21_WebApi11

21)   Install “IP and Domain restrictions” role on the VM

Step26_IPRestriction

22)   Now open IIS and Navigate to WebAPI service web and click “IP Address and Domain restrictions” and add all the client IP’s which requires access to WebAPI.

 

Step27_IpFiltering

This project is hosted in codeplex for download: https://spangular.codeplex.com/ 

 

 

 

 

Azure hosted SharePoint apps using AngularJS and WebAPI – Part 1


This is first post of a three part series on exploring Azure hosted SharePoint apps using AngularJS and WebAPI.

Part 1: Why Cloud and AppModel?

Part 2: SQLAzure data via WebAPI:

Part 3: Azure hosted apps using AngularJS and WebAPI

 Why Cloud?

After SharePoint conference 2014 I became a supporter of cloud based infrastructure and app model. With the sophistication and attractive pricing models from cloud providers, most of the IT enablers started thinking about cloud fork lifts and migrating the existing apps, DB’s and other artifacts to cloud.

Why AppModel?

Over the past few years, App model rapidly became a standard in developing apps and adopted by few big names such as Facebook, Twitter, Dropbox, LinkedIn and yes Microsoft. App model enables custom apps to consume these services via REST\O-Data interfaces.  App authorization process is fairly similar across all these platforms where app registration process generates AppID and AppSecret. Then these custom apps call the services with these tokens for initial authorization.

Slide1

What is different with SharePoint App Model?

Though all the other services provides JavaScript libraries to consume their resources virtually anywhere on the internet with basic xxx.client.authenticate() function, SharePoint\Office365 JSOM models requires SP.ClientContext() with appweb reference to access its resources. Behind the scenes it downloads ~appweburl/_layouts/15/AppWebproxy.aspx (server side code) in to an IFrame to check the request origin. If the client call originates from startpage which is not registered by the app, Office365 doesn’t service the request. This start page could be anything ranging from ASPX or PHP which supports HTTP GET and POST.

 


<?xml version="1.0" encoding="utf-8"?>

<!--Published:70EDFC97-B41D-43C5-B751-7C00AD999804-->

<!--Created:cb85b80c-f585-40ff-8bfc-12ff4d0e34a9-->

<App xmlns="http://schemas.microsoft.com/sharepoint/2012/app/manifest" Name="SharePointApp4" ProductID="{bd366f4e-9a41-4486-9328-476097e36187}" Version="1.0.0.0" SharePointMinVersion="16.0.0.0">

<Properties>

<Title>SharePointApp4</Title>

<StartPage>https://spangular.azurewebsites.net/?{StandardTokens}</StartPage>

</Properties>

<AppPrincipal>

<RemoteWebApplication ClientId="929f258f-1a01-44ff-b7aa-57ff32755db9" />

</AppPrincipal>

</App>

[/xml]

 

Azure based enterprise Apps:

But still there are there are quite a few options to design cloud hosted apps. This article explains azure hosted enterprise app integrated with SQL azure. Basic architecture is shown below.

AzureHostedApps_Architecture

Some of the features are

1)       App is Hosted on Azure website

2)      Consumes WebApi services from SQL azure

3)      Utilizes AngularJS framework to create SPA’s

4)      Clean URL for easy navigation

5)      Responsive design using Hot Towel solution from John Papa

6)      No server side code

7)      Scalable for further enhancements

Step1_Final

 

 

Step2_Responsive