Provision OneDrive and set global administrator for OneDrive accounts in Office365

Recently I was working in a project to migrate all the SharePoint on-premise stuffs to Office365 including file shares. All the users had their on file shares mapped to their home drives on the PC. And the requirement is to move all the home drive data to OneDrive for Business and let the Global administrators to manage them efficiently.

Though Office 365 admin page have functionality to set Global admin for SharePoint sites, for OneDrive sites there is no OOB way to set a Global admin for all the sites. And its very tedious to set this manually for 400+ users.

Below script will help the IT pro’s to

1) Store the Office admin credentials

2) Provision OneDrive Sites for list of users

3) Assign administrator for provisioned OneDrive sites


Download the script and change the Variables in “Input Variables” section to suit your environment

#Input Variables Begin
 #Credentials Store Location
 #Log File location
 $Logfile = "C:\GG\OneDriveProvisionReport.log"
 #O365 Global admin
 $O365AdminAccount = "";
 #O365 Onedrive admin
 $OneDriveAdminAccount = "";
 #O365 Admin site URL
 $webUrl = ""
 #List of OneDrive users (seperated by CSV)
 $OneDriveUsers = "","" 
# Input Variables End

Click here the download the script.

Jumpstart AngularJS app development for O365 & E2E testing using Protractor

BDD (Behaviour Driven Development) and TDD ( Test Driven Development) has become cornerstone for modern Javascript app development but adopting these development strategies to SharePoint/Office 365 is not a trivial task.

I was intrigued to discover #Protractor, an AngularJS testing framework. With client side MVC/MVVM frameworks getting popular among the developers, AngularJS is the premier framework to develop Office365/SharePoint 2013 apps. Integrating TDD methodologies to app development model will help developers to deliver maintainable, flexible and extensible solutions and interfaces.

Below is the RevealJS presentation on how to create AngularJS based SharePoint app and execute end to end testing using #Protractor. I would like to thank Andrew Connell for introducing  RevealJS and AngularJS Apps

This presentation includes training videos and Source code to build SharePoint
1) Expenses AngularApp(SharePoint hosted App)
2) ExpensesAngularApp test (NodeJS project created using VS2013)
1. Expenses AngularApp:
– This is a SharePoint hosted app developed using popular angular framework.
– Utilizes best patterns and practises for angular framework based on HotTowel framework and Learning-Path- Manager-Code-Sample from Andrew Connell.
– Uses ShareCoffee Javascript library to make REST calls to SharePoint
– Available as a nuget package for easy install
2. ExpensesAngularApp test:
– This Project runs on NodeJS and executes End to End testing on Expenses Angular App
– Utilizes Protractor framework to do E2E testing
– Jasmine is used to write test specs
Source code:

My favorite Nuget Packages for WebAPI /MVC apps

Its been a while since I worked on a hardcore ASP.NET / MVC projects. I was not aware of some of the sleek Nuget packages which are used elsewhere.

When you create MVC/WebAPI project by default VS adds packages.config to maintain a record of all the Nuget packages added to the solution.

You can either add packages directly to this file or via “Manage Nuget packages” or  through PowerShell.

Here are some of my favorite packages.

<?xml version="1.0" encoding="utf-8"?>
 <package id="Antlr" version="" targetFramework="net451" />
 <package id="bootstrap" version="3.0.0" targetFramework="net451" />
 <package id="DotNetOpenAuth.AspNet" version="" targetFramework="net45" />
 <package id="DotNetOpenAuth.Core" version="" targetFramework="net45" />
 <package id="DotNetOpenAuth.OAuth.Consumer" version="" targetFramework="net45" />
 <package id="DotNetOpenAuth.OAuth.Core" version="" targetFramework="net45" />
 <package id="DotNetOpenAuth.OpenId.Core" version="" targetFramework="net45" />
 <package id="DotNetOpenAuth.OpenId.RelyingParty" version="" targetFramework="net45" />
 <package id="Elmah.Contrib.WebApi" version="" targetFramework="net45" />
 <package id="elmah.corelibrary" version="1.2.2" targetFramework="net45" />
 <package id="Elmah.MVC" version="2.1.1" targetFramework="net45" />
 <package id="EntityFramework" version="6.1.1" targetFramework="net451" />
 <package id="jQuery" version="1.10.2" targetFramework="net451" />
 <package id="jQuery.UI.Combined" version="1.11.1" targetFramework="net45" />
 <package id="jQuery.Validation" version="1.13.0" targetFramework="net45" />
 <package id="JsonValue" version="0.3.0" targetFramework="net45" />
 <package id="knockoutjs" version="3.2.0" targetFramework="net45" />
 <package id="Microsoft.AspNet.Cors" version="5.2.0" targetFramework="net451" />
 <package id="Microsoft.AspNet.Membership.OpenAuth" version="2.0.1" targetFramework="net451" />
 <package id="Microsoft.AspNet.Mvc" version="5.2.2" targetFramework="net45" />
 <package id="Microsoft.AspNet.Razor" version="3.2.2" targetFramework="net45" />
 <package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net451" />
 <package id="Microsoft.AspNet.WebApi" version="5.2.0" targetFramework="net451" />
 <package id="Microsoft.AspNet.WebApi.Client" version="5.2.2" targetFramework="net45" />
 <package id="Microsoft.AspNet.WebApi.Core" version="5.2.2" targetFramework="net45" />
 <package id="Microsoft.AspNet.WebApi.Cors" version="5.2.0" targetFramework="net451" />
 <package id="Microsoft.AspNet.WebApi.HelpPage" version="5.2.2" targetFramework="net45" />
 <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.2" targetFramework="net45" />
 <package id="Microsoft.AspNet.WebPages" version="3.2.2" targetFramework="net45" />
 <package id="Microsoft.AspNet.WebPages.Data" version="3.2.0" targetFramework="net451" />
 <package id="Microsoft.AspNet.WebPages.WebData" version="3.2.0" targetFramework="net451" />
 <package id="Microsoft.Bcl" version="1.1.9" targetFramework="net45" />
 <package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" />
 <package id="Microsoft.Data.Edm" version="5.6.0" targetFramework="net451" />
 <package id="Microsoft.Data.OData" version="5.6.0" targetFramework="net451" />
 <package id="Microsoft.Data.Services.Client" version="5.6.0" targetFramework="net451" />
 <package id="Microsoft.jQuery.Unobtrusive.Ajax" version="3.2.0" targetFramework="net45" />
 <package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.0" targetFramework="net45" />
 <package id="Microsoft.Net.Http" version="2.2.28" targetFramework="net45" />
 <package id="Microsoft.Web.Infrastructure" version="" targetFramework="net451" />
 <package id="Microsoft.WindowsAzure.ConfigurationManager" version="2.0.3" targetFramework="net451" />
 <package id="Modernizr" version="2.6.2" targetFramework="net451" />
 <package id="MvcSiteMapProvider.MVC5" version="4.6.15" targetFramework="net45" />
 <package id="MvcSiteMapProvider.MVC5.Core" version="4.6.15" targetFramework="net45" />
 <package id="MvcSiteMapProvider.Web" version="4.6.1" targetFramework="net45" />
 <package id="netfx-Guard" version="" targetFramework="net45" />
 <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net451" />
 <package id="Ninject" version="" targetFramework="net45" />
 <package id="Ninject.Extensions.Logging" version="" targetFramework="net45" />
 <package id="Ninject.Extensions.Logging.Log4net" version="" targetFramework="net45" />
 <package id="Ninject.Web.Common" version="" targetFramework="net45" />
 <package id="Ninject.Web.WebApi" version="" targetFramework="net45" />
 <package id="NotFoundMvc" version="1.2.0" targetFramework="net45" />
 <package id="Pkcs12ProtectedConfigurationProvider" version="1.0.1" targetFramework="net45" />
 <package id="Postal.Mvc5" version="1.0.0" targetFramework="net45" />
 <package id="RazorEngine" version="3.4.1" targetFramework="net45" />
 <package id="Respond" version="1.2.0" targetFramework="net451" />
 <package id="ServiceStack.Text" version="4.0.31" targetFramework="net45" />
 <package id="System.Spatial" version="5.6.0" targetFramework="net451" />
 <package id="WebActivatorEx" version="2.0.1" targetFramework="net45" />
 <package id="WebApi.Core" version="0.3.0" targetFramework="net45" />
 <package id="WebApi.Enhancements" version="0.3.0" targetFramework="net45" />
 <package id="WebGrease" version="1.5.2" targetFramework="net451" />
 <package id="WindowsAzure.Storage" version="" targetFramework="net451" />



Powershell to change UPN/Sign-in names for Office 365 users


In many cases after running the DirSync, Office 365 users are created with as Primary UPN.



Internally MS maintains two domains for federated users. One is “” which is the replica of on premise AD and other with “” on Azure AD.

It seems if the Dirsync is ran without “E-Mail” attribute on AD, Azure assigns “” as the default domain and primary UPN. Once the initial DirSync is complete, adding “Email” value to AD user object wont help.



As usual PowerShell comes to rescue. Idea is to use Windows Azure AD Module for Powershell and change the UPN of all the objects with .onmicrosoft UPN.


1) Download and Install Azure AD modules from

2) Connect to WAAD  service using Office 365 admin credentials

3) Filter all the users ending with  as their UPN

4) Change the UPN using Set-MsolUserPrincipalName

5) Generate reports before and after updates

Download the scripts here: Update-msolUpn.ps1 


#.SYNOPSIS ./Update-msolUpn.ps1
#PowerShell script to automate this task to change the all Office 365 user accounts with to
#Install Azure AD modules from before running this.

#Get Modules
$env:PSModulePath=$env:PSModulePath+";"+"C:\Program Files (x86)\Microsoft SDKs\Windows Azure\PowerShell"
Import-Module Azure
Import-Module MSOnline

Get-Credential "" | Export-Clixml C:\GSI\scripts\GSIcred.xml #Store Credentials

#$count = 1 #For Testing the first result

$cred = Import-Clixml C:\GSI\scripts\GSIcred.xml

Connect-MsolService -Credential $cred

Get-MsolUser -All | Select-Object UserPrincipalName, Title, DisplayName, IsLicensed | export-csv –path C:\GSI\scripts\GSI_MSOL_Users_BeforeUpdate.csv

Get-MsolUser -All |
 Where { $_.UserPrincipalName.ToLower().EndsWith("") } |
 ForEach {
 #if($count -eq 1) #For Testing the first result
 # {
 $upnVal = $_.UserPrincipalName.Split("@")[0] + ""
 Write-Host "Changing UPN value from: "$_.UserPrincipalName" to: " $upnVal -ForegroundColor Magenta
 Set-MsolUserPrincipalName -ObjectId $_.ObjectId -NewUserPrincipalName ($upnVal)
 # }

Get-MsolUser -All | Select-Object UserPrincipalName, Title, DisplayName, IsLicensed | export-csv –path C:\GSI\scripts\GSI_MSOL_Users_AfterUpdate.csv


Powershell to report memory leaks and assembly info on SharePoint 2013/2010 custom solutions.


Recently I was involved in a task to troubleshoot performance related issues on a SharePoint farm. On analyzing the farm I found more than 50 WSP’s are deployed. On further analysis some of these solutions had two major performance related issues:

SharePoint Objects are not disposed properly:

Windows SharePoint Services object model contains objects which are not managed by ASP.Net windows garbage collector. Developers must take precautions when using these objects to avoid their long-term retention in memory in the Microsoft .NET Framework.

In scenarios in which you use SharePoint objects extensively—for example, in SharePoint sites that use custom Web Parts—you can cause the following unusual behaviors by not disposing of SharePoint objects when you are finished with them. This results in

  • Frequent recycles of the Windows SharePoint Services application pool, especially during peak usage
  • Application crashes that appear as heap corruption in the debugger
  • High memory use for Microsoft Internet Information Services (IIS) worker processes
  • Poor system and application performance

For more details refer this link

 Production solutions built in debug mode instead of release mode:

The default build setting during development is “Debug” mode and it is a common mistake to allow this development time setting to find its way onto production servers during deployment.  This can often leads to

  • The compilation of ASP.NET pages takes longer (since some batch optimizations are disabled)
  • Code can execute slower (since some additional debug paths are enabled)
  • Much more memory is used within the application at runtime
  • Improper recycles of App pools etc

More details here:


Though the only known solution is re-build these custom WSP’s using best practices, its important to develop a detailed report on each custom assemblies on GAC and provide a report to fix these issues. So idea is to build a powershell script to

1) Export all the WSP solutions

2) Extract the WSP’s

3) Run SPDispose check on each DLL

4) Identify the assembly is in “Debug” or release mode

5) Export the report to CSV




Before running the script install SPDisposeCheck tool from here

Download this script here:


#Creates SP Dispose report on all WSP's

Add-PSSnapin Microsoft.SharePoint.PowerShell -erroraction SilentlyContinue

$wspdir = "D:\WSP\WSPReport1" #Location to export all WSP's
$exportdir = "$wspdir\Export-$((get-date).toString('yyyyMMdd'))\"
$CSVLocation = "$wspdir\SPDisposeResults.csv"

#create directory

#Function to export all WSP's
function Export-AllWSPs
 Write-Host Exporting solutions to $wspdir
 foreach ($solution in Get-SPSolution)
 $id = $Solution.SolutionID
 $title = $Solution.Name
 $filename = $Solution.SolutionFile.Name
 Write-Host "Exporting $title to ¦\$filename" -nonewline
 try {
 Write-Host "– done" -foreground green
 Write-Host "– error : $_" -foreground red


#Function to extract all WSP Packages
function Extract-AllWSPs
 #Retrieve the wsp files in this folder and subfolders
 $s = [system.IO.SearchOption]::AllDirectories
 $fileEntries = [IO.Directory]::GetFiles($wspdir,"*.wsp",$s);
 foreach($fullFileName in $fileEntries)
 $fileName = $(Get-Item $fullFileName).Name;
 $dirName = $fileName.Replace(".wsp","");
 $extractPath = $exportdir + $dirName;
 $dir = [IO.Directory]::CreateDirectory($extractPath) 

 Write-Host "Export $fileName started" -ForegroundColor Red
 $destination = $extractPath
 C:\Windows\System32\extrac32.exe $fullFileName /e /Y /L $destination


#Function to get Assembly details
function Get-AssemblyCustomProperty
 $Property = $null

 $value = $null
 foreach ($attribute in $assembly.GetCustomAttributes($false))
 if ($attribute.GetType().ToString() -like "*$TypeNameLike*")
 if ($Property -ne $null)
 # Select-Object -ExpandProperty fails if property value is $null
 try {
 $value = $attribute | Select-Object -ExpandProperty $Property
 catch {
 $value = $null
 $value = $attribute


#Function to report SP Dispose check results
Function Get-SPDisposeResults()

 #Pause for 5 secs to ensure extract is complete
 Start-Sleep -s 5
 $Dir = get-childitem $wspdir -recurse
 $List = $Dir | where {$_.extension -eq ".dll"}
 $List | ForEach-Object {

 [string]$report = & "C:\Program Files (x86)\Microsoft\SharePoint Dispose Check\SPDisposeCheck.exe" $_.fullname
 #remove repetitive strings
 $report = $report -replace "Note: This tool may report errors which are not actually memory leaks, otherwise known as false positives. Further investigation should be done to identify and correct real errors. It is designed to assist developers in making sure their code adheres to best practices for memory allocation when using SharePoint APIs. Please see the following for more information:", ""
 $build = "RELEASE";
 try {
 $info = @{}
 $assembly = [Reflection.Assembly]::LoadFile($_.FullName)
 $attr = $assembly.GetCustomAttributes([Diagnostics.DebuggableAttribute], $false)
 $info.IsJITTrackingEnabled = Get-AssemblyCustomProperty -Assembly $assembly -TypeNameLike 'System.Diagnostics.DebuggableAttribute' -Property 'IsJITTrackingEnabled'
 #$info.IsJITOptimizerDisabled = Get-AssemblyCustomProperty -Assembly $assembly -TypeNameLike 'System.Diagnostics.DebuggableAttribute' -Property 'IsJITOptimizerDisabled'
 #$info.DebuggingFlags = Get-AssemblyCustomProperty -Assembly $assembly -TypeNameLike 'System.Diagnostics.DebuggableAttribute' -Property 'DebuggingFlags'
 #Write-Host $_.FullName: +" IsJITTrackingEnabled "+ $info.IsJITTrackingEnabled
 #Write-Host $_.FullName: +" IsJITOptimizerDisabled "+ $info.IsJITOptimizerDisabled
 #Write-Host $_.FullName: +" DebuggingFlags "+ $info.DebuggingFlags

 } catch {
 throw $_

 Write-Host $report

 # Create a hash table with all the data
 $hash = @{
 "Assembly" = $
 "Report" = $report
 "Debug Mode enabled" = $info.IsJITTrackingEnabled

 # Convert the hash to an object and output to the pipeline
 New-Object PSObject -Property $hash

#Function calls
Get-SPDisposeResults | Export-Csv -NoTypeInformation -Path $CSVLocation


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.





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




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

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


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


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



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.


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


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:  **//-->



<title>App Launcher</title>


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


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

<!-- Vendor Scripts -->















<!-- Bootstrapping -->






<!-- common Modules -->





<!-- common.bootstrap Modules -->



<!-- app -->






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

<!-- app Services -->








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

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


'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);


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.


'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 ={





service.hostWeb = spweb;


function init(){

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










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 +"//"+ $;

$.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 **// -->





Now add the following code to web.config remove the static file issue on described here

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




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

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




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”

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


'use strict';


var serviceId ='datacontext';

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


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

var $q = common.$q;



var service ={

getPeople: getPeople,

getMessageCount: getMessageCount,

getUserName: getUserName,

getCustomers: getCustomers,

getSPContacts: getSPContacts



return service;


function getCustomers(){


var dfd = $q.defer();

var webApi = $resource('',{ Id:"@Id"},{ update:{ method:'PUT'}});

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


var customers = data;







return dfd.promise;



function getUserName(){


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);


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


var appWeb = ctx.get_web();

var hostWeb = hostWebctx.get_web();

var currentAppWebUser = appWeb.get_currentUser();

var currentHostWebUser = hostWeb.get_currentUser();








var userName = currentAppWebUser.get_title();


},function(sender, args){

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




return dfd.promise;



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);


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


var appWeb = ctx.get_web();

var hostWeb = hostWebctx.get_web();


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

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




var enumerator = contactListItems.getEnumerator();

var SPContacts =[];


var currentItem = enumerator.get_current();

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


var SPContactsObj = SPContacts;



},function(sender, args){

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



return dfd.promise;




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


'use strict';

var controllerId ='dashboard';

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


function dashboard(common, datacontext){

var getLogFn = common.logger.getLogFn;

var log = getLogFn(controllerId);


var vm =this; ={

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 ={













function activate(){

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

common.activateController(promises, controllerId)

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



function getCustomers(){


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


return vm.Customers = data;




function getMessageCount(){

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

return vm.messageCount = data;




function getPeople(){

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

return vm.people = data;





function getSPContacts(){


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

return vm.SPContacts = data;





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



14)   Now add remote endpoint to the appmanifest.xml


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


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


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


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


19)   Add a site name and click create


20)   Keep the default settings and click publish.


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


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


This project is hosted in codeplex for download: 

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.

1)       Create a SQL server instance in Azure management portal -> SQL Databases -> New



2)      Create SQL Database. I am using AdventureWorksLT2012 database for this demoapp. This is downloaded from . After restoring this app on local instance, create a database in SQLAzure with the same name.


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


4)      Now migrate the SQL DB from local instance to SQL azure using SQLAzure Migration Wizard.


5)      SQLAzure supports only a subset of SQL features. Some of the limitations are listed here . XML Schema collections are not supported so uncheck it.


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


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


8)      Now connect to SQLAzure using SSMS


9)      Now to expose the database via WebAPI.

To do this install Azure SDK by following this link

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

10)   Create new “Windows Azure Cloud Service” project. This creates a project with web role. Refer “Cloud Services” section in the article to understand more on this. Basically this project creates a VM and IIS in Azure to host WebAPI web services on deployment.



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.


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


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.







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;


// Web API routes




name: "DefaultApi",

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

defaults: new { id =RouteParameter.Optional }


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


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




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.



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.


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.


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


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


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


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.



This project is hosted in codeplex for download: