📊

SharePoint Framework で Common Data Service のデータを読み取る

に公開

はじめに

SharePoint Framework では AadHttpClient を使うことで Azure AD で保護された API に対してのアクセスを簡単に実装できます。同じ Azure AD で保護されている Common Data Service (Dynamics 365) のデータにもアクセスできるため、今回はその方法を解説します。

事前準備

Web API へのアクセス許可を与えるには、package-solution.json に webApiPermissionRequests を記述します。この記述に従い、SharePoint 管理センターで API のアクセス許可を承認できるようになります。しかし、Common Data Service の場合、次のように記述してもうまくいきません。

{
  "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
  "solution": {
    "name": "SampleApplication",
    "id": "ad9139c7-12db-470b-937d-54967f418959",
    "version": "1.0.0.0",
    "includeClientSideAssets": true,
    "isDomainIsolated": false,
    "webApiPermissionRequests": [
      {
        "resource": "Common Data Service",
        "scope": "user_impersonation"
      }
    ]
  },
  "paths": {
    "zippedPackage": "solution/sharepoint-framework-read-dynamics.sppkg"
  }
}

これは、Common Data Service という名前のサービス プリンシパルが複数存在し、表示名で紐づけしようとすると別のサービス プリンシパルに結びついてしまうことが原因のようです。SharePoint Framework の問題ですが、公式でも表示名を指定するように注釈があるため、何らかの理由があると考えられます。

resource プロパティの値には、アクセス許可を要求するアプリケーションの displayName を指定する必要があります。リソースの指定に objectId を使用すると、アクセス許可の要求を承認しようとしたときにエラーが発生します。

https://docs.microsoft.com/ja-jp/sharepoint/dev/spfx/use-aadhttpclient?WT.mc_id=M365-MVP-5002941

このため、Common Data Service へのアクセス許可を与えるには、Azure ポータルで操作する必要があります。SharePoint Framework は SharePoint Online Client Extensibility Web Application Principal を使用します。このアプリケーションを編集することで、SharePoint 管理ポータルでの承認と同じことができます。

SharePoint 管理ポータルから見た場合も、承認された要求として表示されます。ただし、SharePoint Framework のアプリ名などのメタ情報は表示されません。

これで Common Data Service に接続できます。

サンプル コード

https://github.com/karamem0/samples/tree/master/sharepoint-framework-read-dynamics

実行手順

src/webparts/my-application/SampleApplicationWebPart.ts

context を渡すことを忘れないようにしてください。endpoint は Dynamics 365 の URL を指定します。

export default class SampleApplicationWebPart extends BaseClientSideWebPart<ISampleApplicationWebPartProps> {

  public render(): void {
    const element: React.ReactElement<ISampleApplicationProps> = React.createElement(
      SampleApplication,
      {
        context: this.context,
        endpoint: this.properties.endpoint
      }
    );

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

}

src/webparts/my-application/components/SampleApplication.tsx

componentDidMount メソッドで AadHttpClient を使い、Common Data Service Web API へのリクエストを実行します。今回は標準のエンティティのデータを取得しますが、カスタムエンティティについても同様に取得可能です。

export default class SampleApplication extends React.Component<ISampleApplicationProps, ISampleApplicationState> {

  public componentDidMount(): void {
    if (this.props.endpoint == null) {
      return;
    }
    this.props.context.aadHttpClientFactory
      .getClient(this.props.endpoint)
      .then((client: AadHttpClient) => {
        client
          .get(this.props.endpoint + "/api/data/v9.0/accounts", AadHttpClient.configurations.v1)
          .then((response: HttpClientResponse) => response.json())
          .then((response: any) => {
            this.setState({ accounts: response.value as Array<IAccount> });
          });
      });
  }

}

実行結果

実行すると、以下のようにエンティティのデータが取得できていることを確認できます。なお、Common Data Service のライセンス (Power Apps や Dynamics 365 Sales など) がないユーザーの場合は表示できませんので注意してください。

おわりに

直接 Azure AD のアプリケーションを操作する方法は少しトリッキーですが、使えるテクニックなのでぜひ試してみてください。

Discussion