Wednesday 27 March 2019

Service Locator pattern in SPFx: Using Service Scopes

I have written about this topic in the past but with the recent increase in SharePoint Framework adoption and with more features becoming available (e.g. MSGraphClient, AadHttpClient), I felt it would be a good time to revisit this.

With SPFx solutions getting more complex day by day and with lots of components to manage, passing the web part (or extension) context around to different parts of your code can get difficult to maintain real fast.

The problem:


For example, imagine we have created a custom service which needs the MSGraphClient to make a call to the Microsoft Graph and we are consuming this service in our SPFx webpart. To initialise the service, we need to either pass in the entire web part context to it, or explicitly pass in the MSGraphClient object from the context.

In the first case, we are unnecessarily passing in all other objects in the context to this service as well.

And in the second case, our code becomes tightly coupled i.e. in the future, if our service needs something else from the webpart context, we have to update the service as well as the consuming code (i.e. the webpart) to pass in the new dependency.

The solution:


Using the Service Locator pattern in SPFx through service scopes, we can abstract away the implementation details of our custom services from the calling code (i.e. webparts, extensions).

With service scopes, we can get hold of instances of SPFx classes like MSGraphClient, AadHttpClient, SPHttpClient and PageContext from our services without having to explicitly pass them in from the webparts.



In this post, lets see how to achieve this:

1) Calling the MSGraphClient from a custom service:



Consuming the custom service from an SPFx webpart:


If you observe the code, our calling webpart does not have any knowledge of the implementation details of the custom service, specifically the fact that it used the MSGraphClient internally to retrieve the current user details. In the future, if we wanted to change the implementation of the service, we could do it without changing any web part code.

2) Calling the AadHttpClient from a custom service:


Similarly, we can also use service scopes to get hold of an instance of the AadHttpClient class. In the code below, to keep things simple, I am using the AadHttpClient to make a call to the Microsoft Graph. Eventually, the result is the same as the previous code but it should demo how to use the AadHttpClient through service scopes.


Consuming the custom service from an SPFx webpart:



3) Calling the SPHttpClient from a custom service:


And finally, if we just want to make a call to the SharePoint REST API from our SPFx code, we can also use service scopes to get hold of an instance of the SPHttpClient class. The following code also demonstrates how to get an instance of the PageContext class to get different run time context values like the current web url. Using the current web url, we can make a call to the SharePoint REST API to get the web details:


Consuming the custom service from an SPFx webpart:


And that's it for this post! I am planning more posts on this topic in the future so keep an eye out for those :)

As always, the code from this post is available on GitHub: https://github.com/vman/ServiceScopeTestBench

Monday 4 March 2019

Create Azure DevOps pipelines for a Microsoft Teams app built with SPFx

In this post, let's walk-through the configuration needed to create Azure DevOps build and release pipelines for a Microsoft Teams solution. 

The solution is built using the SharePoint Framework and will be surfaced in Microsoft Teams as a Tab. 

As the code for the SPFx solution is being hosted in a GitHub repository, I will only focus on the Azure Pipelines configuration. For information on how to work with Azure Repos, see the official Microsoft docs: https://docs.microsoft.com/en-us/sharepoint/dev/spfx/toolchain/implement-ci-cd-with-azure-devops

These are the high level steps we are going to follow:

Build pipeline:


1) Create production package of the SPFx solution (.sppkg)
2) Create a Teams manifest package (.zip) 
3) Publish the SPFx and Teams packages as Artefacts to be consumed from the Release pipeline

Release pipeline:


1) Deploy the SPFx package to the SharePoint Tenant App Catalog (using the Office 365 CLI)
2) Deploy the Teams manifest package to the Microsoft Teams App Catalog (using the Office 365 CLI)

So without further ado, here are the screenshots and scripts to achieve this:

(Click on the images to zoom)

Build pipeline:



Use Node 8.12.0:


npm install:


gulp bundle --ship:


gulp package-solution --ship:


The .sppkg file needs to be copied to staging directory in order to be published to the release pipeline:


Create a .zip file for the teams app catalog and copy it to the staging directory as well:


Publish the .sppkg and .zip files so that they can be consumed from the Release pipeline:



Release pipeline: 


Now to create a new Release Pipeline which will deploy the packages to the respective app catalogs in the tenants.

The Artefacts used will be the .sppkg file and the .zip file for Teams which was published in the previous step:


Overview of tasks in the Release pipeline:


Before moving on to the tasks, we also need to configure some variables to hold the information for the tenants, credentials etc.


The username and password should be for an account with global admin permissions. This is because the Microsoft Graph API (used by the Office 365 CLI) needs this permission to deploy apps to the Microsoft Teams App catalog:
https://docs.microsoft.com/en-us/graph/api/teamsapp-publish?view=graph-rest-1.0#permissions

The TeamsManifestId will be used to check if the app already exists in the Teams App catalog. This can be fetched from the manifest.json file in the teams folder of the SPFx solution:


If you are feeling adventurous, you could look at cracking open the .zip file from the Release pipeline and then grabbing the id on-the-fly instead of having to specify it in a variable.

Next, we will need to use Node (same task as the build pipeline) and install the Office 365 CLI on the Release agent using:

npm install -g office365-cli


Next, we need to deploy the SPFx package to the SharePoint Tenant App Catalog:


Here is the script as a gist:

And lastly, we need to publish the Teams manifest to the Microsoft Teams App Catalog. We will do this using the Office 365 CLI as well. Thanks to Elio and Waldek to get this functionality in the Office 365 CLI at lightning speed!


Here is the script as a gist:

And that's it! You now have build and release pipelines configured to deploy SPFx solutions and Teams apps. The webpart will now be available in SharePoint and the tab will be available in Teams:



 Hope you found this walk-through useful!