SPFx – Using MSGraph API

Introduction

Hi friends, in this post let us see what is MSGraph, how can it be of use for us in SharePoint Framework.

What is MSGraph?

Microsoft Graph acts as a gateway to all the services in Microsoft 365. It is a generic programming model to access enormous amount of data from various services in cloud. More details can be found here.

Using MSGraph API in SPFx

Why we need to use MSGraph API in SPFx? since we have many frameworks and inbuilt API’s to access data from SharePoint. Each and every service has their own API’s then why we need to go for the new API. The answer is very simple, its a single point of contact for all the services. One API for almost all the Microsoft 365 service, how cool is it?

Focus on Code

Let us see some different options of accessing the Graph API. Below are the options we are gonna focus in this post. You have to understand that there is only one API and options are just how to call the API with the params.

  • Using MSGraphClient from @microsoft/sp-http
  • Using graph from @pnp/graph

Let us start by creating a new web part project using yeoman SharePoint generator, before that create a folder where you want to create the web part. Navigate to that folder and run the below command

yo @microsoft/sharepoint

The generator will asks you couple of questions,

  • Enter the webpart name as your solution name, and then select Enter.
  • Select Create a subfolder with solution name for where to place the files.
  • Select Y to allow the solution to be deployed to all sites immediately.
  • Select N on the question if solution contains unique permissions.
  • Enter the webpart name
  • Enter the webpart description
  • Choose the framework as ‘React

Once the project is created, install the pnp modules from npm using the below command. I had created a webpart with a name MsGraphApiSample

npm i @pnp/graph @pnp/odata --save

Open the code in VSCode which is my favorite and flexible code editor for SharePoint Framework. You can directly open the project folder from the file menu or use the below command to open the VSCode from command line.

cd \web part folder\
code .

Navigate to your <Webpart>.ts file and import the following modules

import { graph } from "@pnp/graph";
import { MSGraphClient } from '@microsoft/sp-http';

Delete the default description property and make sure your code looks like the below

export interface IMsGraphApiSampleWebPartProps {
    client: MSGraphClient
}

Inside the class method, setup the graph context for the pnp/graph module to get access.

protected onInit(): Promise<void> {
        return super.onInit().then(_ => {
            graph.setup({
                spfxContext: this.context
            });
        });
    }

Inside the render method, pass the client property which is provided by the SPFx by default context.

public async render(): Promise<void> {
        const element: React.ReactElement<IMsGraphApiSampleProps> = React.createElement(
            MsGraphApiSample,
            {
                client: await this.context.msGraphClientFactory.getClient()
            }
        );

        ReactDom.render(element, this.domElement);
    }

Navigate to your <webpart>.tsx file and copy-paste the below imports. Here we are using the selective imports for pnp modules, which make the package size small instead of importing all the unused modules. More detailed explanation can be found here.

import { MSGraphClient } from '@microsoft/sp-http';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
import { graph } from "@pnp/graph";
import "@pnp/graph/users";
import "@pnp/graph/insights";
import "@pnp/graph/batch";
import "@pnp/graph/messages";

Do not forget to update the I<webpart>Props.ts file to remove the description and to add the client property.

export interface IMsGraphApiSampleProps {
    client: MSGraphClient;
}

Now let us declare an interface for maintaining the state value which is used for displaying the loading indicator and then to display the JSON output.

export interface IMsGraphApiSampleState {
    loading: boolean;
    result: string;
}

Copy-paste the below content within the class. There are 6 buttons designed to execute the method to call the graph API using the default MSGraph Client and PnPGraph module.

constructor(props: IMsGraphApiSampleProps) {
        super(props);
        this.state = {
            loading: false,
            result: ''
        };
    }

    private _getCurrentUserInfo = async () => {
        this.setState({
            loading: true,
            result: ''
        });
        let userInfo: any = await this.props.client.api('/me').get();
        this.setState({
            loading: false,
            result: JSON.stringify(userInfo, undefined, 2)
        });
    }

    private _getTrendingItems = async () => {
        this.setState({
            loading: true,
            result: ''
        });
        let trendingItems: any = await this.props.client.api('/me/insights/trending').get();
        this.setState({
            loading: false,
            result: JSON.stringify(trendingItems, undefined, 2)
        });
    }

    private _getBatchResponse = async () => {
        this.setState({
            loading: true,
            result: ''
        });
        let batchReqests: any = {
            "requests": [
                {
                    "url": "/me?$select=displayName,jobTitle,userPrincipalName",
                    "method": "GET",
                    "id": "1"
                },
                {
                    "url": "/me/messages?$filter=importance eq 'high'&$select=from,subject",
                    "method": "GET",
                    "id": "2",
                    "DependsOn": [
                        "1"
                    ]
                },
                {
                    "url": "/me/events?$select=subject,organizer",
                    "method": "GET",
                    "id": "3",
                    "DependsOn": [
                        "2"
                    ]
                }
            ]
        };
        let batchResponse: any = await this.props.client.api('$batch').post(batchReqests);
        this.setState({
            loading: false,
            result: JSON.stringify(batchResponse, undefined, 2)
        });
    }

    private _getPnPUserInfo = async () => {
        this.setState({
            loading: true,
            result: ''
        });
        let userInfo: any = await graph.me.get();
        this.setState({
            loading: false,
            result: JSON.stringify(userInfo, undefined, 2)
        });
    }

    private _getPnPTrendingItems = async () => {
        this.setState({
            loading: true,
            result: ''
        });
        let trendingItems: any = await graph.me.insights.trending.get();
        this.setState({
            loading: false,
            result: JSON.stringify(trendingItems, undefined, 2)
        });
    }

    private _getPnPBatchResponse = async () => {
        this.setState({
            loading: true,
            result: ''
        });
        let batch = graph.createBatch();
        let userRes = null;
        let messageRes = null;
        graph.me.select('displayName', 'jobTitle', 'userPrincipalName').inBatch(batch).get().then((o) => {
            userRes = o;
        });
        graph.me.messages.select('from', 'subject').inBatch(batch).get().then((o) => {
            messageRes = o;
        });
        await batch.execute();
        this.setState({
            loading: false,
            result: JSON.stringify(userRes, null, 4) + JSON.stringify(messageRes, null, 4)
        });
    }

    public render(): React.ReactElement<IMsGraphApiSampleProps> {
        return (
            <div className={styles.msGraphApiSample}>
                <div className={styles.container}>
                    <div className={styles.row}>
                        <div className={styles.column}>
                            <div>
                                <div><h3>Using MSGraph Client</h3></div>
                            </div>
                            <DefaultButton onClick={this._getCurrentUserInfo}>Get User Info</DefaultButton>
                            <DefaultButton onClick={this._getTrendingItems}>Get Trending Items</DefaultButton>
                            <DefaultButton onClick={this._getBatchResponse}>Get Batch Response</DefaultButton>
                            <div>
                                <div><h3>Using PnPGraph</h3></div>
                            </div>
                            <DefaultButton onClick={this._getPnPUserInfo}>Get User Info</DefaultButton>
                            <DefaultButton onClick={this._getPnPTrendingItems}>Get Trending Items</DefaultButton>
                            <DefaultButton onClick={this._getPnPBatchResponse}>Get Batch Response</DefaultButton>
                            {this.state.loading &&
                                <div><h4>Please wait, loading...</h4></div>
                            }
                            {this.state.result &&
                                <div style={{ wordBreak: 'break-word', maxHeight: '400px', overflowY: 'auto' }}>
                                    <pre>{this.state.result}</pre>
                                </div>
                            }
                        </div>
                    </div>
                </div>
            </div>
        );
    }

Preview

Source Code

The source code along with other samples can be found in the below github link.

SPFx-Demos

Happy Coding…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s