This blog is about SharePoint, Office365 and Office Development

Popular Posts

Microsoft Teams:Your enterprise bot is here Part I

Yesterday Microsoft Announced "Microsoft Teams" the chat based workspace in Office 365 https://blogs.office.com/2016/11/02/introducing-microsoft-teams-the-chat-based-workspace-in-office-365/

I've waited for a long time to have an enterprise chat based application that I can connect my sample meeting booking bot which I've created back in April 2016. see my previous office 365 bot post

When I navigated back to my bots page and I immediately found that Microsoft Team channel is already added to the available channels . 
I was thrilled and excited , with  only two mouse clicks I was able to connect my previously built bot to My Microsoft Team desktop application.



You have to have the desktop version installed in order to add the bot as a chat contact. However, you can carry on with the conversation using either desktop app or the web interface.

here is a conversation summary with the same bot 


and here I can see my upcoming meeting which the bot created for me


This is all happened without leaving Microsoft teams app, you can use any bot published in the bot directory or create your own enterprise bot to have a robust experience without the need to switch your context. 

This is just a very basic thing I've tried with simple clicks without changing a single line of code.

Next, I will try to see what user context properties I can capture to enhance my bot functionality

Happy Office Development

SharePoint Framework: Angular2 Sample

This post is about two firsts. My very first Angular2 app ever and my first SharePoint Framework client webPart. If you don't have your machine ready yet for the new awesome SharePoint framework follow the guide described @ https://github.com/SharePoint/sp-dev-docs to set up your environment before trying to create this angular2 sample.
Generate Client WebPart
Follow yo generator steps and at the technology stack we will choose the first option (no framework) as currently there is no option for angular2 (hopefully Microsoft will add this in a future version of SharePoint client-side solution generator)
Add Angular2 Goodness
Create a new directory under src/webPart and name it app (we will put all the angular component and module files in this directory)
Create a new file AppComponent.ts and paste the sample code below to create our Angular2 Component

Let's create our angular2 module appmodule.ts
Bootstrap Angular2 Module inside WebPart Render Method
Before we bootstrap the angular2 module we need to import the module and some other dependencies
Now let's bootstrap the angular2 module in our Angular2SampleSPFx.ts file
Install dependencies
Let's install the needed dependencies

we also need to enable experimental decorators in tsconfig.json file

Build And Try the WebPart
Let's build& run our webPart
And here is the webPart in action
Note: If you try to add multiple webParts of our Angular2SampleSPFx it simply won't work
The code sample can be found @https://github.com/ministainer/Angular2SampleSPFx

New Document Library Experience : Part II Custom Actions


In my pervious post I explained the newly introduced experience with a deep dive explaining the various building blocks of the page. In this post, I will focus more on one particular action which is  the custom action, and how it has been affected by the new experience.

Custom Action Navigation Action

Custom actions are handled using "odsp-next/actions/odb/CustomActionNavigationAction" module. In this module, a simple check to UrlAction property value is done. The decision is solely based on whether it starts with the string "javasctipt:"  or not . In the first case, a call to executeCustomActionJSCode function will be performed. However, in the second case(when you simply register UrlAction as a simple link) new window will open and navigate to the desired web address.



Note:When you register your custom action using visual studio , the custom action ActionUrl property will be converted to Javascript:LunchApp(yourUrl,popup options)

popup options will always be null unless you use dialog width and height parameters in the custom action definition in Visual Studio elements.xml File. If the popup options parameter is not null, a  Javascript error will be thrown. To reproduce this simply try any custom action with dialog parameters , deploy it to SharePoint library as ECB or ribbon button.


Before execute javascript code block window.RegisterSod is called for alot of SharePoint files which used to be included/registered via masterpage

Any ScriptLink Globally registered script is no longer executed in the new experience pages like document library/site contents.

Url Token Replacement

Another important notice that not all the tokens within the ActionUrl will be replaced, only the following token will be replaced if you are using the new SharePoint library experience.
  1. {ItemId}
  2. {ListId}
  3. {Source}
  4. {SiteUrl}
  5. {ItemUrl}
  6. {SelectedItemId}
  7. {ListUrlDir} 

What to expect next:

Currently all the customization opens the classical SharePoint dialog doesn't work in the new document library experience, it will be nice if Microsoft release the new extensibility framework which will eventually replace the old dialog with the ability to create your own action handlers,components and executors similar to rename out of the box actions:

RenameActionHandler

RenameActionExecutor




New Document Library experience: deep dive Part I



Recently the new SharePoint document library experience has been released, you probably have already seen it if your tenant is on First Release.

Exactly one week ago Stefan Bauer published a very insightful blog post focusing on the main building blocks of the new SharePoint document library experience.

Although I have no previous experience with either ReactJS or knockoutJS I decided to give it a try and attempt to figure out the building blocks in more details:

Let's have a look on the Files 

I won't write any details around the framework used as Stefan covers it brilliantly in his blog in addition to the main pillars (RequireJS , React, Knockout JS), you can find bundled and minified version of files delivered via akamaihd.net CDN with the subdomain spoprod-a (SharePoint Online Production) can't really figure out the "-a" part of the subdomain name.



Note: facebook use the same CDN as well.

After a quick look at the HTML elements, I can see several components within the page, when you trace it down you have two main components ms-spo-app and ms-files

ms-file contains around 14 child components:

  • ms-suite-nav                       (top navigation component)
  • ms-left-pane                       (left navigation component)
  • ms-search                           (search)
  • od-userFeedback                (feedback link)
  • ms-drag-and-drop               (enabling drag and drop files)
  • od-overlay-host                   (container for the ECB Item menu) 
  • od-dialog-host                     (container for dialogs like rename dialog)
  • ms-panel-host
  • ms-hidden-dom-host
  • od-transclusion-host          ( info right panel)
  • ms-standalone-list              (This is the main component for the list
  • ms-command-bar               (list commands "ribbon replacement")
  • ms-siteHeaderKOHost


In this blog i will focus on one component , so let's take a look at the new right info

The new Info Panel


If you click on the info icon to the right you can see recent activities and number of documents in the current view. However if you do select a specific file you can see file preview and number of sections:

Overview Section

This section always appear. However, it appears in two different renditions if the document is selected an iframe will be rendered to review the document using wopiFrame.aspx page.

Other sections 

The other sections:
Recent Activity, Properties, Sharing, Information will appear based on collection calculated by function called availableSections()

here is function execution in case of  no file is been selected ,we notice that it's only single section with a component named "ms-activities-feed"



and if a single file is been selected, more sections appears in the availableSections call to render 
document edit form , sharing and infomation




What happens when you change item selection 

When the user select a document and the right information panel is active, series of network activities is fired up to get the data necessary to render the right information panel



File Sharing Settings

Two different calls to  2 different point to gather sharing information 



File Properties

A single request to RenderExtendedListFormData which  passes the following parameters:
  • Item Id  
  • form Id  : string representation of the form 'edit form'
  • mode 
  • options 

I couldn't figure out either the mode or the options yet

In the next part I will talk more about different actions which can be found in file https://spoprod-a.akamaihd.net/files/odsp-next-prod_ship-2016-07-11_20160715.004/splistdeferred.js:

and I will focus on one particular action odsp-next/actions/odb/CustomActionNavigationAction which handles the execution of UrlAction custom action and how the new document library experience affects (at the moment) any existing document library based customization.


OfficeDev: Building CrossPlatform SharePoint Custom Action using NodeJS


This post is a part of a series focused in building SharePoint extensions using NodeJS, the aim of this series is to provide a guide on how to build cross platform SharePoint solutions. In case of Office Add-ins office generator makes it very easy for us to build cross platform Office Add-ins. However, to extend SharePoint contextual add-ins we were always stuck with Visual studio or using Napa and build SharePoint hosted apps.

In this post I will explain how to build and deploy  a NodeJS Provider-hosted app with Custom Action that updates the Item Title.

The Add-in will consist of Three Major parts



App Principle



For simplicity I will focus on apps with apponly mode switched on, to get a new app principle simply navigate to  https://yourtenantname.sharepoint.com/_layouts/AppRegNew and generate  new App Id and secret.

In my case I will deploy the custom action to a new azure website called "o365-customaction"  so I've added o365-customaction.azurewebsites.net as my "app domain"

In the permission textbox I've added the following permissions giving my app tenant full control
save your app Id and secret and move on to the next step

App Web


When using Visual Studio template this will be created for us automatically when we choose to build a provider-hosted app or once we enable or add any remote event receiver, in this case let's use yo express to scaffold a basic nodejs web app for us.
  1. Install express yo generator
  2. Create new app
  3. Let's configure handling custom action via new middleware using  
  4. Create the update item handler
  5. O365Connect.js handles getting apponly token and update the list item
  6. Deploy web app to azure 
  7. To Deploy your web app to azure you need to install azure-cli package globally for more details check my previous post at http://www.sharepointtweaks.com/2015/10/building-outlooj-add-in-using-office-yo-generator.html
  8. At this step I assume you can deploy your nodejs website to azure using azure local repository and azure-cli

Deploying SharePoint Artifacts

At this moment we have a NodeJS web application running in azure, within the context of this web app user have full control of your SharePoint Online tenant. The missing piece is to create the custom action. One quick solution is to use powershell to create the custom action however, this will defy the purpose of this post which is making SharePoint development cross-platform.

RESTful APIs to the rescue

Using the SharePoint RESTful APIs you can retrieve and update any web custom user actions using basic http request by executing GET, DELET, POST HTTP requst to the /_api/web/customactions end point

Introducing gulp-sharepoint


This is a seed for a nodejs module that can be used to deploy SharePoint artifacts as gulp task currently it used to only deploy SharePoint custom action as gulp task



Hooking it up with deploy command

by adding the following lines to deploy.cmd this will allow this task to run whenever you update the azure local git repository the current logic of adding custom action is removing any old custom action that has the same name

See it in action !


What Next?

Anything is possible, you can easily build a complete set of cross-platform CLI tools to talk to SharePoint RESTful APIs and build the app web using any technology  stack you desire.



Building an Office Assistant using botframework: v3 update

Almost couple of months ago I published a complete three part walk-through:
Part I (http://www.sharepointtweaks.com/2016/04/officedev-introducing-office365-bot.html)
PartII (http://www.sharepointtweaks.com/2016/05/officedev-introducing-office365-bot.html)
Part III (http://www.sharepointtweaks.com/2016/05/officedev-introducing-office365-botpart3.html))

The walk-through focused on building an office assistant bot using Luis.ai and botframework. However,  last weekend I received an announcement email introducing the newer version of botframework (v3), so I decided to migrate my existing Office assistant bot from the old v1 botframework to v3.

I've published a new branch to my git repository which includes a working version 3 of the same very basic meeting booking bot

you can have a look at
https://github.com/ministainer/O365-Assistant/tree/v3





OfficeDev: Inconvenient SharePoint App only permission using Azure AD Apps

App Only Permission using AAD App and SharePoint online
I was playing around with adal-node trying to build a remote event receiver using NodeJS, however I stumble on a big issue, which is even my Azure AD App explicitly has SharePoint Online added as a resource with all app only permission set selected I always got a strange error "unsupported app only token" I find out that my fellow MVP  John Liu faced a similar problem and he explained it in details in his post here with a fix using certificates.



Inspecting SharePointContext.cs


By Looking at SharePointContext.cs abstract class which is generated when you add SharePointPnPCoreOnline nuget package to your visual studio project I notice in this case app only permission works fine for SharePoint online!
By going through the code and with little help of ILSPY I manage to understand how the accesstoken is being generated using SharePointContext  and TokenHelper classes to access SharePoint online via client credentials, the flow is as below:

  1. get realm by executing dummy call to client.svc and reading the www-authenticate header 
  2. update client_id to be on the format client_id@realm
  3. update resource to be string concatenation of the following
    1. SharePoint Principle always =00000003-0000-0ff1-ce00-000000000000
    2. your tenant subdomain *.sharepoint.com
    3. realm value
  4. executing a client_credential token POST request to https://accounts.accesscontrol.windows.net/{realm}/tokens/OAuth/2

by executing this request in postman I manage to get access_token for SharePoint online 


Creating NodeJs Module

After this small experiment I figured I will create a small nodejs package so it can be used to connect to SharePoint online using client Id and secret without the need for a certificate in the same manner any command line application created using visual studio can.

I've created nodejs module and published it here @https://github.com/ministainer/SharePoint-apponly-node

The modeul is also published @https://www.npmjs.com/package/sharepoint-apponly-node you can install it by simply

and here is how to use it



The repos is just a seed will add token refresh and cache capabilities later.


OfficeDev: Yet a more CI friendly version of Office Generator "Yo Office"

In this post I will explain in details how to update Office generator template to generate more CI friendly version  by updating dist gulp task

Building blocks
The building blocks for any Office Add-in (with exception of SharePoint Add-ins) is simply a manifest file and a web application, the manifest file holds all the information the office client need to know about the addin like ribbon Commands, Publisher and version information. Most importantly It contains the url of the actual web application rendered within wither Office Online or office client.

How to Build Office Add-ins
To build office add-ins you can simply use either Visual Studio template shipped as part of Development tools for Office or Yeoman Generator template for cross platform development.

today we will focus on a simple modification of the existing office generator template, let's take a look at the existing template code here https://github.com/officedev/generator-office if we take a look at the generated gulpfile.js for our office add-in for example let's take a look at generated gulpfile.js at  https://github.com/OfficeDev/generator-office/blob/master/generators/content/templates/common/gulpfile.js

we can see that the dist task consist of simple subtasks which clean the destination folder , copy files and minify all the scripts.


If we go ahead and generate  a new add-in using the current version of office generator after running gulp dist to generate we can locate out manifest file in our output ./dist folder and we can see that all urls are basically pointed out to localhost.


The Solution
Having the generator as an open source solution allows anyone to easily fork it to his/her repository my fork which contain the generated gulpfiles.js update can be found at https://github.com/ministainer/generator-office

I've created a simple gulp task called replace-url and add it to the list of substasks of dist task



as you can see the simple added code depends on 'gulp-replace' and 'yargs' modules


now let's start testing the new generator , linking generator-office template to my code

run the generator passing --url parameter

now the generated manifest file has the passed URL as base URL

access the code @https://github.com/ministainer/generator-office

OfficeDev: Introducing Office365 Bot your office 365 assistant is here --Part 3


In the previous posts we saw how to create a bot using botframework and integrate it to LUIS platform to process the textual user input and generate user intents and entities which are more likely to be understood by our application then normal text.

In  this post we will integrate our Office365 assistant bot into Skype bot in a simple configuration steps. we do not need to rewrite any of the code we've already have before. In a similar manner our bot can be connected to other various bots.

Creating a Skype bot
without digging into further details about Skype bot , you  can find a lot of details here , the most important step is when creating a bot under messaging webhook make sure you got the URL copied from your generic bot

Use the below URL and place your bot Id as query string parameter
https://skype.botframework.com/Dev/?botId={Your bot ID here} for example using our previous bot example we can use

https://skype.botframework.com/Dev/?botId=EmailAssistantDemo

Testing our bot in Skype
after creating the bot you will find a button that suggest adding the bot as Skype contact it will redirect to a URL

https://join.skype.com/bot/{your_bot_id}


After adding the bot as Skype contact we can find it online as in the below image


As we can see the Email assistant bot is not available for messaging, so let's start our bot locally

In the generic bot definition we need to publish accessible URL we can easily deploy our bot to azure website or simply use a tool like ngrok to tunnel connection to our localhost


now a *.ngrok.io link will be generated so let's substitute end point with this new value and let's add /api/messages as a suffix.



now let's really test our bot integration with Skype

Connected bots vs. Specific platform bots

Building bots as connected bot not vs. building  a platform specific bot is basically depends on your bot scenario for example connected bots are good if you don't require a specific requirement based on the bot conversation context and you would like to share the same behavior between different bots. However having the conversation context of the bot is a good advantage so we can deliver a tailored experience based on user behavior which depends on the platform capabilities.