SharePoint Framework で Common Data Service のデータを読み取る
はじめに
SharePoint Framework では AadHttpClient
を使うことで Azure AD で保護された API に対してのアクセスを OAuth の設定を行うことなく簡単に実装することができます。ということは Common Data Service (Dynamics 365) のデータにもアクセスできるはずなので試してみたいと思います。
事前準備
通常、SharePoint Framework に対して 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 を使用すると、アクセス許可の要求を承認しようとしたときにエラーが発生します。
ということで、Common Data Service へのアクセス許可を与えるために、Azure ポータルで操作することになります。SharePoint Framework は SharePoint Online Client Extensibility Web Application Principal というアプリケーションに対してアクセス許可を与えています。直接このアプリケーションを編集することで SharePoint 管理ポータルでの承認と同じことを行うことができます。
SharePoint 管理ポータルから見たときも承認された要求として表示されています。ただし SharePoint Framework のアプリ名などのメタ情報は表示されないみたいですね。
ともあれ、これで Common Data Service に接続できるようになりました。
サンプル コード
実行手順
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