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