CSOM で通知を取得するときの仕様が鬼畜な件について
はじめに
SharePoint にはリスト アイテムに変更があったときにメールで通知をしてくれる機能があります。上位互換の Power Automate を使うという方法もありますが、モダン UI にもちゃんとメニューがあり、組み込みのお手軽さもあるため、まだまだ使う機会は多いです。
CSOM では Web.Alerts プロパティでサイトに設定されている通知の一覧を取得できます。しかし、思わぬところでうまくいかないことがあるため、紹介します。
ItemID プロパティを Load に含めるとエラーが発生する
通知にはリスト全体に設定するものと特定のリスト アイテムのみに設定するものがあります。それぞれは ListID プロパティと ItemID プロパティによって特定できます。試しに ListID プロパティと ItemID プロパティを取得してみます。それぞれは既定では読み込まれないため、明示的に指定する必要があります。
private static void Main(string[] args)
{
var siteurl = "{{site-url}}";
var username = "{{user-name}}";
var password = "{{password}}";
var credential = new NetworkCredential(username, password);
var context = new ClientContext(siteurl)
{
Credentials = new SharePointOnlineCredentials(credential.UserName, credential.SecurePassword)
};
context.Load(context.Web.Alerts, x => x.Include(y => y.ListID, y => y.ItemID));
context.ExecuteQuery();
}
このコードを実行すると、以下のエラーが発生します。
Microsoft.SharePoint.Client.ServerException: 'ItemID is not available for this type of alert.'
リスト全体に設定する通知の場合、ItemID プロパティを参照しようとすると強制的にエラーが発生します。安全に読み込むには、それぞれの Alert について AlertType プロパティを判断し、読み込むプロパティを変える必要があります。つまり、以下のようなコードになります。
private static void Main(string[] args)
{
var siteurl = "{{site-url}}";
var username = "{{user-name}}";
var password = "{{password}}";
var credential = new NetworkCredential(username, password);
var context = new ClientContext(siteurl)
{
Credentials = new SharePointOnlineCredentials(credential.UserName, credential.SecurePassword)
};
context.Load(context.Web.Alerts);
context.ExecuteQuery();
foreach (var alert in context.Web.Alerts)
{
switch (alert.AlertType) {
case AlertType.List:
context.Load(alert, x => x.ListID);
break;
case AlertType.Item:
context.Load(alert, x => x.ListID, x => x.ItemID);
break;
default:
context.Load(alert);
break;
}
context.ExecuteQuery();
}
}
AlertTime プロパティを Load に含めるとエラーが発生する
AlertTime プロパティでも同様の事象が起こります。
private static void Main(string[] args)
{
var siteurl = "{{site-url}}";
var username = "{{user-name}}";
var password = "{{password}}";
var credential = new NetworkCredential(username, password);
var context = new ClientContext(siteurl)
{
Credentials = new SharePointOnlineCredentials(credential.UserName, credential.SecurePassword)
};
context.Load(context.Web.Alerts, x => x.Include(y => y.AlertTime));
context.ExecuteQuery();
}
このコードを実行すると、以下のエラーが発生します。
Microsoft.SharePoint.Client.ServerException: 'AlertTime property cannot be used on immediate alerts.'
コードは省略しますが、この場合も AlertFrequency プロパティを見て Immediate かどうかで読み込みを変える必要があります。
おわりに
汎用的な設計になっているために取得する側で工夫が必要です。もし利用する場合は十分注意してください。
Discussion