C# SPO CSOM .Net CoreでExecuteQueryAsyncが動かなかったときの話

話の発端はこんな依頼からだった。
「Azure FunctionsからSharePoint OnlineへCSOMでアクセスできない??」

普通にCSOMのライブラリを使えばいけるだろ!と思っていただが、約半日もハマってしまったので覚書。

開発言語はC#で、Visual Studio 2019を使用。

スポンサーリンク

Azure Functionsは.Net Core

まず最初にハマったのが、Azure FunctionsをC#で実装する場合は.Net Coreが対象になる、という点。

下の公式ページに書いてあるのだが、Azure Functionsのランタイムv2とv3は.Net Coreが対象。
Azure Functions ランタイム バージョンの概要

ランタイムv1は.Net Frameworkを対象としているが、今回こちらは選択肢にはなかった。

.Net Coreであることの何が問題か?
それは、.Net Core上でCSOMを動作させるための情報が少なすぎるという点。

.Net CoreとCSOMライブラリ

.Net Core上でCSOMとつなごうとした場合、ちょっとめんどくさい手順を踏むことになる。
詳しくはこちら(Qiita)で紹介してくれているが、もう少し手順を詳しく説明。

まずはV16のCSOMパッケージをインストールする。
Visual StudioのNuGetマネージャーで「CSOM」と検索するとパッケージがたくさんでてくるので、V16のパッケージをインストール

続いて、.Net Coreに必要なライブラリのみを参照するように設定する。
まずは、ソリューションエクスプローラーで[依存関係]-[パッケージ]を開いて、先ほどインストールしたCSOMパッケージを見つける
そのCSOMパッケージのプロパティを開くと、インストールされた場所が見れる。

その場所をエクスプローラーで開くとこんなフォルダ構成になっているので、
netcore45フォルダに

  • Microsoft.SharePoint.Client.Portable.dll
  • Microsoft.SharePoint.Client.Runtime.Portable.dll

が、
net45フォルダに

  • Microsoft.SharePoint.Client.Runtime.Windows.dll

があることを確認する

そしたらVisual Studioに戻って、上の3つのdllへの参照を追加し、Microsoft.SharePoint.Client.dllとMicrosoft.SharePoint.Client.Runtime.dllへの参照を消す。
僕はめんどくさかったので、CSOM V16のパッケージを全消しして、上の3つの参照を追加した。

これでようやく開発の準備が整った。

ExecuteQuery・・・Async??

今回一番ハマったのがここ。ExcecuteQueryにAsyncがついちょる。。。
ひとまず普通に作ってみよう!と思って作ったコードがこちら。

// url:SharePointサイトのURL、accountID:アカウントID、password:パスワード
using (ClientContext context = new ClientContext(url))
{
   context.Credentials = new SharePointOnlineCredentials(accountID, password);
   FileCreationInformation fileCreation = new FileCreationInformation();
   fileCreation.Content = System.Text.Encoding.UTF8.GetBytes("ファイルの内容");
   fileCreation.Overwrite = true;
   fileCreation.Url = "SampleText.txt";

   List spList = context.Web.Lists.GetById(new Guid("ドキュメントライブラリのID"));
   Microsoft.SharePoint.Client.File uploadFile = spList.RootFolder.Files.Add(fileCreation);

   context.Load(spList);
   context.Load(spList.RootFolder);
   context.Load(uploadFile);

   context.ExecuteQueryAsync().Wait();
}

何のことはない、GUIDで指定したドキュメントライブラリの直下にSampleText.txtファイルを追加するだけのプログラム。
普通のCSOMライブラリであればこれで動作した。

なのに.Net Core上では動かない。コードは特に問題なく終了しても動かない。
なんでだろ。。。

ということで、しばらく悩んだ結果、動作したコードがこちら。

using (ClientContext context = new ClientContext(url))
{
   context.Credentials = new SharePointOnlineCredentials(accountID, pass);

   FileCreationInformation fileCreation = new FileCreationInformation();
   fileCreation.Content = System.Text.Encoding.UTF8.GetBytes("ファイルの内容");
   fileCreation.Overwrite = true;
   fileCreation.Url = "SampleText.txt";

   List spList = context.Web.Lists.GetById(new Guid("ドキュメントライブラリのID"));
   Microsoft.SharePoint.Client.File uploadFile = spList.RootFolder.Files.Add(fileCreation);

   context.Load<List>(spList);
   context.Load<Folder>(spList.RootFolder);
   context.Load<Microsoft.SharePoint.Client.File>(uploadFile);

   context.ExecuteQueryAsync().Wait();
}

ジェネリックかーい!Async関係ないんかーい!

ということで、Loadをジェネリックにしたら無事動作した。

まとめ

今回、開発していて何が一番困ったかというと情報が全然ないこと。

もちろん公式のドキュメント「ClientContext.ExecuteQueryAsync method」も見てみたんだけど例は書いてないし、ExecuteQueryAsyncって調べるとJavaScriptやSilverLightのコードがたくさん出てきて探すのも大変だし、と久しぶりにドハマりした内容でした。

コメント

タイトルとURLをコピーしました