からめもぶろぐ。

SharePoint が得意なフレンズなんだね!すごーい!

CSOM の WebTemplate には Path が入ってこない件

どういうことかというと、以下のコードを実行します。

public static class Program {

    private static void Main(string[] args) {
        var siteUrl = "<サイトの URL>";
        var userName = "<ユーザー名>";
        var rawPassword = "<パスワード>";
        var securePassword = new SecureString();
        foreach (var c in rawPassword) {
            securePassword.AppendChar(c);
        }
        var credentials = new SharePointOnlineCredentials(userName, securePassword);
        var clientContext = new ClientContext(siteUrl) {
            Credentials = credentials
        };
        var webTemplates = clientContext.Web.GetAvailableWebTemplates(1041, true);
        clientContext.Load(webTemplates);
        clientContext.ExecuteQuery();
        var webTemplate = webTemplates.FirstOrDefault(x => x.Name == "STS#0");
        Console.ReadLine();
    }

}

はい、そうですね。Path プロパティの値が null になります。

どういうことだってばよ

CSOM では自らのオブジェクトの場所を特定するために、オブジェクトが Load された後、識別情報を Path プロパティに保持します。*1 たとえばリスト アイテムだと以下のような値が入っています。

5e66049e-800e-4000-b805-a573a858fe86|740c6a0b-85e2-48a0-a494-e0f1759d4aa7:site:217cc400-7454-40e2-8f0d-546625dfb9fb:web:564072f0-9feb-48d6-b7bc-f77e17623c87:list:00077cba-a4e8-460f-a2b3-3a96a2da523f:item:1,1

「site:<GUID>」とか「web:<GUID>」となっているのがそれぞれの親オブジェクトの ID です。Load メソッドを呼び出すときは常にこの値を見るため、WebTemplate を Load しようとすると常に例外が発生します。

WebTemplate も ClientObject の派生クラスなので同じ動きしてくれないと困るのですが。

*1:Load メソッドの呼び出し前は ObjectPathPropertyObjectPathMethod のような参照情報が入っています。

SPClient 0.12 をリリースしました

www.powershellgallery.com

また 0.11 のリリース告知を忘れてましたので、0.11 と 0.12 の変更点をまとめます。

新たに追加された関数はないのですが、パラメーターの名前が変わったり、既定の動作が変更されたりしています。例えば NoEnumerate パラメーターの追加により、パイプラインでの処理に柔軟性を持たせることができるようになりました。ちなみに内部的には NoEnumerate の値はそのまま Write-Output に渡されています。

SPClientContentType でリスト コンテンツ、SPClientField でサイト列がそれぞれサポートされました。パラメーターに Web を渡すか List を渡すかの違いだけです。

SPClient 0.10 をリリースしました

www.powershellgallery.com

オンライン ヘルプを作りました。PowerShell のヘルプ ドキュメントから Markdown への変換は platyPS というモジュールが役に立ちます。Microsoft の PowerShell Team で開発しており、なかなかいい感じです。

github.com

あとは細かい修正ですが、Use-SPClientType 関数で C:\Program Files\Common Files\Microsoft Shared\Web Server Extension を参照するのをやめて、GAC を参照するようにしました。複数バージョンのアセンブリが入っている場合は新しい方を参照するので、どうしても 2013 (15.0.0.0) バージョンを使いたい場合はパスを指定してください。

SharePoint Online の Excel Services (SOAP API) を叩いてみる

Excel Services を使うと SharePoint のドキュメント ライブラリに保存されている Excel ファイルを直接編集することができます。プログラムから Excel を編集というと Open XML SDK を使うか、サードパーティー製のコンポーネントを使うかという話になるのですが*1、Excel Services を使えばセルの読み書き程度であれば簡単にできてしまいます。SOAP なので Visual Studio からは [サービス参照の追加] で簡単に呼び出すことができます。

ただし SharePoint Online の場合はこの方法では問題があります。SharePoint Online は OAuth なので、対応していないと思われる WCF ではアクセス許可が通りません。なので、自力で HTTP ヘッダーを追加してあげる必要があります。

サンプル コード

github.com

Access Token の取得方法は以下の記事を参考にしてください。今回のサンプルでは Refresh Token を使った Access Token の再取得も実装しています。

blog.karamem0.jp

WCF でカスタム HTTP ヘッダーを追加するには Message Inspectors という機能を使えばいいようです。

IClientMessageInspector を実装するクラスを作ります。メッセージを送信する前に Bearer Token を追加します。

public class BearerClientMessageInspector : IClientMessageInspector {

    public object BeforeSendRequest(ref Message request, IClientChannel channel) {
        var property = new HttpRequestMessageProperty();
        property.Headers.Add("Authorization", "Bearer <Access Token>");
        request.Properties[HttpRequestMessageProperty.Name] = property;
        return null;
    }

    (snip)

}

IEndpointBehavior を実装するクラスを作り、ClientRuntime.ClientMessageInspectors にメッセージ インスペクターを追加します。

public class BearerEndpointBehavior : IEndpointBehavior {

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) {
        clientRuntime.ClientMessageInspectors.Add(new BearerClientMessageInspector());
    }

    (snip)

}

SoapClient の EndpointBehaviors にビヘイビアーを追加します。

using (var client = new ExcelServiceSoapClient()) {
    client.Endpoint.EndpointBehaviors.Add(new BearerEndpointBehavior());
    var status = default(Status[]);
    var sessionId = client.OpenWorkbook(FilePath, "", "", out status);
    var cell = client.GetCellA1(sessionId, "Sheet1", "A1", false, out status);
    client.CloseWorkbook(sessionId);
}

*1:まさかこのご時世に Excel COM でやろうとする人はいないですよね?

SPClient 0.9 をリリースしました

www.powershellgallery.com

ファイルとフォルダーに関する関数が追加されました。リスト アイテムとの変換を行う関数も用意しています。
ちなみに ListItem.Folder プロパティの説明だと変換できないときに null を返すと書いてあるのに、実際は ServerObjectIsNull を true にして返すという。ListItem.File プロパティの説明は合ってるのになあ。

ListItem.Folder property (Microsoft.SharePoint.Client)