AxiosでSharepointのリストをAPI操作

Sharepoint Onlineのサイトでカスタムスクリプトが有効になっていると、共有ドキュメントエリアにおいたaspxファイルをjavascriptが有効なウェブフォームページとして利用でき、 デフォルトで用意されているListをデータベース代わりに扱ってシングルページアプリを作れます。

正統ではないのかもしれませんが、こういった形でReact-Appのプロジェクトをホストして動作させることができます。

簡単なアプリを作るため、axiosを使ってAPIを叩きましたが、ドキュメントに例が載っていることもなく、ばらばらに散っていた情報を集めてList操作を実施したのでそのメモに残します。

Sharepoint OnlineのListをAPI操作する

前提となる変数等

const YOUR_SUBDOMAIN="あなたのSharepoint Onlineサイトのサブドメイン";
const SITE_NAME="Sharepointサイト名";
const LIST_NAME="DB代わりに使いたいリスト名";

// ListItemEntityTypeFullName
// 下記で取得できる。APIコール数削減のため直接確認して定数化しておいたほうが吉。
// https://${YOUR_SUBDOMAIN}.sharepoint.com/_api/web/lists/GetByTitle('${LIST_NAME}')?$select=ListItemEntityTypeFullName
const ListItemEntityTypeFullName="上記で取得したEntityFullName";
const EndPoint=`https://${YOUR_SUBDOMAIN}.sharepoint.com/sites/${SITE_NAME}/_api/web/lists/getByTitle('${LIST_NAME}')/items`;
const ContextInfo=`https://${YOUR_SUBDOMAIN}.sharepoint.com/sites/${SITE_NAME}/_api/contextinfo`;

ListからItemをすべて取得

公式ドキュメント通りに動作し、GETで苦労なく取得できました。 前置きの共有ドキュメントにホストする形態をとる場合、ログイン済みの状態でaspxにアクセスしておりヘッダーのAuthorizationは省略できます。以降の別の操作も同じです。 取得あたりの上限件数があった気がしますが、pager型のアクセスで工夫してください。

axios.get(EndPoint)
  .then(response =>{
    // Listの一覧はresponse.data.valueに配列で入っている
    // response.data.valueに含まれるitemのIdがUpdate等の個別操作に必要
    console.log(response.data.value);
  });

ListからIDを指定してItemを個別に取得

一覧取得と同様に公式ドキュメント通りで苦労がないです。

const ItemId=0; // 取得したいItemのId
axios.get(`${EndPoint}(${ItemId})`)
  .then(response =>{
    // response.data直下にリストの情報
    console.log(response.data);
  });

Listに新規アイテムを作成

アイテムの作成・編集にはform_digest_valueが必要で、これは上で定義したContextInfoで取得ができます。

const data={
  Title: "my first post via API"
}
axios.post(ContextInfo, {})
  .then(response =>{
    return axios.post(
      EndPoint,
      data,
      {
        headers: {
          "Content-Type": "application/json;odata=verbose",
          "X-RequestDigest": response.data.FormDigestValue
        }
      }
    );
  }).then(response =>{
    // response.data直下に新規作成したリストアイテムの情報
    console.log(response.data);
  });

List Itemの編集

公式ドキュメントに若干の誤記があり、PR中。Content-Typeを新規アイテム同様にする必要があります。

const data={
  Title: "my first edited post via API"
}
const itemId=0
axios.post(ContextInfo, {})
  .then(response =>{
    return axios.post(
      `${EndPoint}(${ItemId})`,
      data,
      {
        headers: {
          "Content-Type": "application/json;odata=verbose",
          "X-RequestDigest": response.data.FormDigestValue,
          "If-Match": "*",
          "X-HTTP-Method": "MERGE"
        }
      }
    );
  }).then(response =>{
    // response.data直下に編集したリストアイテムの情報
    console.log(response.data);
  });

さらに詳しく

SharePointリスト列に応じてデータのフォーマットが決まっているものがある。

列の型 値の渡し方
Yes/No true/false
選択肢 文字列だが、選択肢で定義されいてる文字列
日付と時刻 ISO String (.toISOString())
ユーザーまたはグループ 内部で定義されているInt型のID (後述)

[ユーザーとグループ]列

リストの操作に[ユーザーとグループ]列を含める場合は少し特殊な準備が必要になる。ちなみにAuthorやEditorという予約済フィールドも同様の構造である。[ユーザーとグループ]はフィールド名ではなく、フィールド名 + Idを操作する。注意として、リストにユーザーがauthorまたはeditorというフィールドを定義した場合、author0Idやeditor0Idを操作する。

ややこしいがドメインでIdは固定されておらず、サイトごとで固有のIdが割り当てられる。

UserIdを知りたい

サイトにおける自分のId
axios.get(`https://${YOUR_SUBDOMAIN}.sharepoint.com/sites/${SITE_NAME}/_api/SP.UserProfiles.PeopleManager/GetMyProperties`)
  .then(response =>{
    console.log(response.data.Id);
  );
他のユーザーのIdをメールアドレスから調べる
const UserEmail = "hogehoge@fugafuga.com";
axios.get(`https://${YOUR_SUBDOMAIN}.sharepoint.com/sites/${SITE_NAME}/_api/SiteUsers/getByEmail('${UserEmail}')`)
  .then(response =>{
    console.log(response.data.Id);
  );

ユーザー情報のリストを得たい

サイトにぶら下がっているユーザー情報一覧で取得する場合

const UserEmail = "hogehoge@fugafuga.com";
axios.get(`https://${YOUR_SUBDOMAIN}.sharepoint.com/sites/${SITE_NAME}/_api/SiteUsers`)
  .then(response =>{
    console.log(response.data);
  );

ユーザー情報を展開して取得する

リストアイテムを取得する際にはサーバー側にId->ユーザー情報展開の処理を指示し、その状態でデータを受け取れる。

const ItemId=0; // 取得したいItemのId
const query="?$select=Title,Author/Title,Author/EMail$expand=Author"
axios.get(`${EndPoint}(${ItemId})${query}`)
  .then(response =>{
    // ユーザー表示名
    console.log(response.data.Author.Title);
    // ユーザーEmail
    console.log(response.data.Author.Email);
    // リストアイテムのタイトル
    console.log(response.data.Title);
  });

[ユーザーとグループ]列にログインユーザーを入れてPostする

以下、フィールド名をPersonField、フィールドに格納されているユーザーのIdがPersonFieldIdで参照できるとして、

const data={
  Title: "my first post via API"
};
const options={
  headers: {
    "Content-Type": "application/json;odata=verbose",
  }
};
Promise.all([
  axios.post(ContextInfo, {})
    .then(response =>{
      options.headers["X-RequestDigest"] = response.data.FormDigestValue;
    }),
  axios.get(`https://${YOUR_SUBDOMAIN}.sharepoint.com/sites/${SITE_NAME}/_api/SP.UserProfiles.PeopleManager/GetMyProperties`)
    .then(response =>{
      data["PersonFieldId"] = response.data.Id;
    })
]).then(() =>{
  return axios.post(
    EndPoint,
    data,
    options
  );
}).then(response =>{
  // response.data直下に新規作成したリストアイテムの情報
  console.log(response.data);
});

参考

No comments:

Post a Comment