Post

Call Dataverse API from SPFx Web Part

In today's data-driven world, it is essential to have seamless integration between different platforms in order to maximize productivity and efficiency. Dataverse is a scalable data service and application platform that allows users to securely store and manage business data used by various applications.

By accessing Dataverse data directly from SharePoint, Outlook, and Teams, users can not only enhance their experience with real-time insights but also reduce the need for redundant storage and synchronization of data. This integration enables users to interact with important business information without leaving their familiar SharePoint, Outlook, or Teams environment, creating a more connected and efficient workflow.

In this post, I will provide a step-by-step guide on how to build a service that retrieves data from Dataverse and performs operations using the SharePoint Framework (SPFX). This solution can be used in SharePoint, Outlook, and Teams environments.

Prerequisites

Before deploying the SPFx solution to interact with Dataverse ensure you have the following:

  1. Dataverse Environment. Access to a Dataverse environment with necessary permissions to read account entity.
  2. Microsoft 365 tenant with appropriate licenses for Dataverse, SharePoint, Outlook, and Microsoft Teams.
  3. Account with the SharePoint Admin or Global Administrator role assigned to deploy the SPFx solution.

The SharePoint Framework (SPFx) is a powerful development tool that allows developers to create custom solutions that integrate seamlessly across different platforms, including SharePoint, Microsoft Teams, and Outlook.

📝 With SharePoint Framework, you can build responsive and mobile-friendly applications and web parts that are consistent across different environments.

Target Solution

The web part we will create must meet the following requirements:

  1. Execute and display the result of the [WhoAmI(https://learn.microsoft.com/en-us/power-apps/developer/data-platform/webapi/reference/whoami?view=dataverse-latest){target="_blank} request.
  2. Display list of entities (accounts).
  3. Support SharePoint, Outlook, and Microsoft Teams as a hosted platform.

Display data stored in Dataverse on SharePoint, Teams, and Outlook

Display data stored in Dataverse on SharePoint, Teams, and Outlook

As you can see, this is a simple web part. Let's code!

Web Part

Using the Yeoman generator for the SharePoint Framework I created a new web part solution and removed any unnecessary components, keeping only the minimum required for the purpose of this article.

💡 Source code: spfx-dataverse.

Project Structure

Project Structure

The structure of the solution is as follows:

  1. src/components contains a single root component and minimal styles
  2. src/model contains definition of the data that the web part works with
  3. src/services contains the service to interact with the Dataverse API
  4. src/webparts contains the web part

As you can see, this is a very simple web part.

Permissions

To call the Dataverse API on behalf of a user, we need to declare the required permissions. Open the config/package-solution.json file and add the webApiPermissionRequests under the solution section.

{
  "solution": {
    "webApiPermissionRequests": [
      {
        "resource": "Microsoft Dataverse",
        "scope": "user_impersonation"
      }
    ]
  }
}

📝 Once the solution has been deployed to the App Catalog, the administrator needs to approve the API permissions for the SPFx solution.

Service

To work with the API, we will create a new service with native SPFx Service Scope that is designed to manage dependencies and optimize resource utilization in web parts and extensions.

Service scopes provide a way to create and manage shared services, promoting reusability and consistency across different components. By using service scopes, developers can define and register services at different levels, such as application, web part, or component, allowing for granular control over service life cycles and dependencies. This approach enhances modularity and simplifies testing and maintenance through the isolation of services and their configurations.

💡 Service Scope is a powerful tool in SPFx that contributes to the development of robust, scalable, and maintainable SharePoint solutions.

We'll create src/services/DataverseService.ts file with the following code:

For ease of reading, some parts of the code have been omitted. The full version of the code is available on GitHub: DataverseService.ts

import { ServiceKey, ServiceScope } from "@microsoft/sp-core-library";
import { jwtDecode, JwtPayload } from "jwt-decode";
// omitted

export default class DataverseService implements IDataverseService {

    // Service key to consume the service
    public static readonly serviceKey: ServiceKey<DataverseService> = ServiceKey.create<DataverseService>('VitalyZhukovDataverseService', DataverseService);

    public constructor(serviceScope: ServiceScope) {
        serviceScope.whenFinished(() => {
            // Initializing token provider and http client
            this._aadTokenProviderFactory = serviceScope.consume(AadTokenProviderFactory.serviceKey);
            this._httpClient = serviceScope.consume(HttpClient.serviceKey);
        });
    }

    public async whoAmI(): Promise<IWhoAmI> {
        const url = `${this._instanceUrl}/api/data/v9.2/WhoAmI`;
        return this.get<IWhoAmI>(url);
    }

    public async getEntityList(entityPluralName: string, fields: string[]): Promise<any> {
        const url = `${this._instanceUrl}/api/data/v9.2/${entityPluralName}?$select=${fields.join(",")}`;
        const data = await this.get<any>(url);
        return data?.value || [];
    }

    /**
     * Execute GET-requests to the Dataverse API
     * @param url Endpoint address to proceed the request
     * @returns Response in JSON format
     */
    public async get<T>(url: string): Promise<T> {
        // Getting token
        const token = await this.getToken();

        // Perform request
        const response = await this._httpClient.get(url, AadHttpClient.configurations.v1, { headers: { Authorization: `Bearer ${token}` } });

        // Cast response to JSON-object
        const data = await response.json();

        if (response.ok) {
            return data;
        }
        else {
            throw data;
        }
    }

    // omitted

    /**
     * Retrieve token to interact with the Dataverse API
     * @returns JWT
     */
    private async getToken(): Promise<string | undefined> {
        if (this.tokenExpired) {
            // Getting instance of the AAD Token Provider
            this._provider = this._provider || await this._aadTokenProviderFactory.getTokenProvider();

            // Retrieve OBO Token
            this._token = await this._provider.getToken(this._instanceUrl);

            // Decode JWT to check expiration timestamp
            this._decodedToken = jwtDecode<JwtPayload>(this._token);
        }

        return this._token;
    }
}

Service Instance

Once registered, we can access the service instance by using the consume method of the Service Scope. This approach allows your components to efficiently and consistently access the necessary services, promoting reusability and modularity.

Open the web part code and add onInit as shown below:

For ease of reading, some parts of the code have been omitted. The full version of the code is available on GitHub: DataverseWebPart.ts

import DataverseService, { IDataverseService } from '../services/DataverseService';

export default class DataverseWebPart extends BaseClientSideWebPart<IDataverseWebPartProps> {
  private _dataverseService: IDataverseService;

  protected async onInit(): Promise<void> {
    // Consume the service
    this._dataverseService = this.context.serviceScope.consume(DataverseService.serviceKey);

    // Provide Dataverse URL to the service
    this._dataverseService.instanceUrl = this.properties.instanceUrl;
  }

By using the Service Scope to consume services, we can better manage dependencies, improve performance, and ensure a clear separation of concerns in your SPFx solutions.

Execution Flow

There are several key steps involved in the execution process.

First, the web part uses the service that handles authentication and API calls. This service obtains an OAuth token from the native SharePoint On-Behalf-Of (OBO) token endpoint, which facilitates secure token exchange. The OBO token allows the web part to act on behalf of the user, ensuring that it can securely access and interact with the Dataverse API.

Once the token is obtained, the service uses it to authenticate with the Dataverse API, allowing the web part to access and manipulate data.

Execution Flow

Execution Flow

By following these steps, SPFx web parts can effectively integrate with external services, providing a robust user experience while maintaining a high level of security.

Deployment

Build and package the solution by running the gulp build and gulp package-solution commands in your development environment.

gulp bundle --ship
gulp package-solution --ship

This will generate the necessary package file in the sharepoint/solution folder.

Navigate to your SharePoint Online App Catalog site and upload the generated .sppkg file to the App Catalog.

Once uploaded, select the package and click on “Deploy” to make the web part available across your tenant.

SPFx Solution Deployment

SPFx Solution Deployment

API Access

Before using the web part, we will need to approve the requested API permissions. To do this, go to the SharePoint Admin Center and select "API access" under the "Advanced" section. Once there, you can approve the request and continue using the web part.

API Access Permissions for SPFx solution

API Access Permissions for SPFx solution

If the permission request is declined or not approved, we will receive an error message:

AADSTS65001: The user or administrator has not consented to use the application with ID '8c57a079-3a24-439f-8c56-bbea68b9e88a' named 'SharePoint Online Client Extensibility Web Application Principal'. Send an interactive authorization request for this user and resource.

Result

We have developed a solution that integrates with Dataverse and can be hosted on SharePoint, Teams, or Outlook.

Entities in Dataverse Table

Entities in Dataverse Table

SharePoint Online

SharePoint Online

Outlook

Outlook

Microsoft Teams

Microsoft Teams

The integration of Dataverse with SharePoint Framework (SPFx) web parts provides a solid foundation for building scalable and efficient solutions within the Microsoft ecosystem.

Summary

In this post, we have explored how to use the Dataverse API within a SharePoint Framework (SPFx) web part. This process involves setting up necessary permissions in Azure Active Directory (AD), configuring the SPFx web part, and authenticating securely to interact with the Dataverse API. Following these steps allows developers to access Dataverse data within SharePoint solutions, improving functionality and user experience.

GitHub

The source code is available on GitHub: github.com/vzhukov/spfx-samples.

Vitaly Zhukov

Vitaly Zhukov

Tech Lead, Architect, Developer, Technical Trainer, Microsoft MVP. Over 20 years of experience in system integration and software development. I specialize in designing and implementing scalable, high-performance software solutions across various industries.

You May Also Like

Provision Lists and Libraries with SPFx solution

Provision Lists and Libraries with SPFx solution

SharePoint. Drag-and-Drop File Uploading

SharePoint. Drag-and-Drop File Uploading

CSOM. Upload document

CSOM. Upload document

SharePoint List REST API. Part 2

SharePoint List REST API. Part 2

SharePoint Framework. Create Angular WebPart

SharePoint Framework. Create Angular WebPart

SharePoint List REST API. Part 1

SharePoint List REST API. Part 1

Project Server. CSOM + Custom Fields

Project Server. CSOM + Custom Fields

SharePoint 2010. Long time operation with updatable status

SharePoint 2010. Long time operation with updatable status

Linq to SharePoint. Cross site collection queries

Linq to SharePoint. Cross site collection queries

SharePoint. Getting Document Icon URL

SharePoint. Getting Document Icon URL

Linq to SharePoint. Repository pattern

Linq to SharePoint. Repository pattern

Linq to SharePoint vs Camlex.NET Performance Comparison

Linq to SharePoint vs Camlex.NET Performance Comparison

Linq to SharePoint. Part 5. Choice and MultiChoice fields

Linq to SharePoint. Part 5. Choice and MultiChoice fields

Linq to SharePoint. Part 4

Linq to SharePoint. Part 4

Linq to SharePoint. Part 3

Linq to SharePoint. Part 3

Linq to SharePoint. Part 2

Linq to SharePoint. Part 2

Linq to Sharepoint. Part 1

Linq to Sharepoint. Part 1