⚙️

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