からめもぶろぐ。

俺たちは雰囲気で OAuth をやっている

Global Microsoft 365 Developer Bootcamp 2019 Tokyo に登壇しました

2019/11/23 に開催された Global Microsoft 365 Developer Bootcamp 2019 Tokyo で Adaptive Cards のハンズオン担当として登壇しました。

connpass.com

「ファイル名を間違えないように」と言っておきながら、自分がファイル名を間違えるという凡ミスがありましたが、最後までハンズオンをやり切れたのでよかったです。
割と早めに資料を作り上げていたのですが、当日までに微妙なアップデートがあって (Azure ポータルの見た目が変わってる、Flow が Power Automate に名称変更している、.NET Core 3.0 が GA している、などなど) いろいろご迷惑をおかけしました。ちゃんと本番前に資料の見直しをしないといけないですね。

スライドは Speaker Deck にアップロードしています。

CSOM で通知を取得するときの仕様が鬼畜な件について

SharePoint にはリスト アイテムに変更があったときにメールで通知をしてくれる機能があります。上位互換の Power Automate を使うという方法もありますが、モダン UI にもちゃんとメニューがあって、組み込みのお手軽さもあるため、まだまだ使う機会は多いでしょう。

CSOM では Web.Alerts プロパティでサイトに設定されている通知の一覧を取得することができます。しかし思わぬところでうまくいかないことがありますのでご紹介しておきたいと思います。

ItemID プロパティを Load に含めるとエラーになる

通知にはリスト全体に設定するものと特定のリスト アイテムのみに設定するものがあります。それぞれは ListID プロパティと ItemID プロパティによって特定することができます。
試しに ListID プロパティと ItemID プロパティを取得してみたいと思います。それぞれは既定では読み込まれないので明示的に指定してあげる必要があります。

private static void Main(string[] args)
{
    var siteurl = "{{siteurl}}";
    var username = "{{username}}";
    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 = "{{siteurl}}";
    var username = "{{username}}";
    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 = "{{siteurl}}";
    var username = "{{username}}";
    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 かそうでないかで読み込みを変える必要があります。

まとめ

完全に使う側のこと考えないで設計しているよなとしか思えないです。もし使われる場合は十分注意してください。

SharePoint 2019 で SPFx の Application Customizer を追加するとフォントが変更される

SharePoint 2019 でコミュニケーション サイトを作成し、SPFx の Application Customizer を追加したときに、フォントが Yu Gothic に変更されるという事象が発生します。

コミュニケーション サイトの最初の状態では、フォントは Segoe UI (日本語はメイリオ) で表示されています。これに何もしない空の Application Customizer を追加すると…?

Yu Gothic になってしまっています。見た目が大きく変わってしまうのでこれは困りますね。

これを回避するには、Application Customizer で元のスタイルシートを当てなおす必要があります。F12 開発ツールで覗くと、

[lang^=ja].ms-Fabric, .ms-Fabric [lang^=ja], [lang^=ja] .ms-Fabric {
    font-family: Yu Gothic,Meiryo UI,Meiryo,MS Pgothic,Osaka,Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif;
}

というスタイルが当たってしまっているようなので、Application Customizer に以下のコードを追加します。

  @override
  public onInit(): Promise<void> {
    const head: HTMLHeadElement = document.getElementsByTagName('head')[0];
    const style: HTMLStyleElement = document.createElement('style');
    style.type = 'text/css';
    style.appendChild(document.createTextNode(`
      [lang^=ja].ms-Fabric, .ms-Fabric [lang^=ja], [lang^=ja] .ms-Fabric {
        font-family: "Segoe UI Web (West European)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif !important
      }
    `));
    head.appendChild(style);
    return Promise.resolve();
  }

ちなみに SharePoint Online では発生しません。なので、今後、SharePoint 2019 のアップデートがあった場合は、現象が解決する可能性はあります。

SharePoint Online のコミュニケーション サイトで評価の設定を有効にする

SharePoint Online のコミュニケーション サイトでは、[リストの設定] にある [評価の設定] の項目がありません。そのため「いいね!」や「星評価」の機能を使うことができないようになっています。
評価の機能は GUI からは設定できませんが、CSOM から機能を有効化することで利用できるようになります。

Add-Type -LiteralPath "$PSScriptRoot\Microsoft.SharePoint.Client.dll"
Add-Type -LiteralPath "$PSScriptRoot\Microsoft.SharePoint.Client.Runtime.dll"

$siteurl = "{{siteurl}}"
$username = "{{username}}"
$password = "{{password}}"

$password = ConvertTo-SecureString $password -AsPlainText -Force
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)
$context = New-Object Microsoft.SharePoint.Client.ClientContext($siteurl)
$context.Credentials = $credentials

$context.Site.Features.Add('915c240e-a6cc-49b8-8b2c-0bff8b553ed3', $true, [Microsoft.SharePoint.Client.FeatureDefinitionScope]::None) > $null
$context.ExecuteQuery()