からめもぶろぐ。

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

SharePoint Framework 1.4.1 で追加された MSGraphClient を試してみた

SharePoint Framework 1.4.1 がリリースされ、プレビューですが Graph API をサポートしました。

Office Dev Center - Now Releasing – Enhanced preview support for Microsoft Graph API calls from SharePoint Framework

これまでのバージョンでは、GraphHttpClient によって限定的な Graph API の呼び出しがサポートされてきましたが、今回のリリースでは、新しい SharePoint 管理センターから承認することで、任意のアクセス許可を与えることができます。
今回のリリースで追加されたのは MSGraphClient という名前になっており、モジュールも @microsoft/sp-client-preview になっています。

docs.microsoft.com

追加のアクセス許可を取得する場合は、package-solution.json にアクセス許可を指定します。アプリ カタログ サイトに登録したときに、承認待ち状態でアプリが登録され、管理者が承認すると許可された API が使用できるようになります。

docs.microsoft.com

ちなみに、残念ながら GraphHttpClient とは違い OAuth で新しいウィンドウを開く動作となっていますが、ポップアップ ブロックが有効になっているときに親切にも教えてくれるようになりました (/・ω・)/

SharePoint でコンテンツ エディター Web パーツが表示されない場合の対処方法

SharePoint Online の場合にコンテンツ エディターが表示されない場合はだいたい以下の理由で解決します。

support.office.com

それ以外の場合でコンテンツ エディター Web パーツが表示されない場合があります。具体的には、サイト コレクションを [テンプレートを後で選択...] で作成したときに発生することがあるようです。サイト コレクション機能の「BasicWebParts」が有効になっていないだけなのですが、非表示になっている機能なので、PowerShell から有効にしてあげる必要があります。

SharePoint Server (オンプレミス) の場合は、管理シェルを使って有効にします。

Enable-SPFeature -Url '<サイト コレクションの URL>' -Identity '00bfea71-1c5e-4a24-b310-ba51c3eb7a57'

SharePoint Online の場合の場合は、CSOM を使って有効にします。

$siteUrl = '<サイトの URL>'
$userName = '<ユーザー名>'
$rawPassword = '<パスワード>'
$securePassword = ConvertTo-SecureString -String $rawPassword -AsPlainText -Force

$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
$ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($userName, $securePassword)
$ctx.Site.Features.Add('00bfea71-1c5e-4a24-b310-ba51c3eb7a57', $true, [Microsoft.SharePoint.Client.FeatureDefinitionScope]::None)
$ctx.ExecuteQuery()

SharePoint 2013 REST API の UserCollection.GetByLoginName メソッドを呼び出すとエラーが発生する

SharePoint 2013 で REST API の UserCollection.GetByLoginName メソッドを呼び出したときに、以下のメッセージでエラーが発生することがあります。

危険な可能性のある Request.Path 値がクライアント (:) から検出されました。

エラーの詳細については @ さんのブログが詳しいです。

blog.daruyanagi.jp

何が問題かというと、SharePoint 2013 以降はクレーム ベース認証なので、ログイン名は「i:0#.w|domain\user」の形式になり、要するに常にコロンが入るってことです。ちなみに SharePoint Online では問題ないです。

(2018/2/9 追記)
GetByLoginName('i:0#.w|domain\user') は駄目で GetByLoginName(@v)?@v='i:0#.w|domain\user' の形式なら大丈夫らしい。なるほど。

第 12 回 Plus Programming .net 勉強会で LT してきました

2018/1/27 に開催された第 12 回 Plus Programming .net 勉強会で LT をしてきました。「TypeScript ビギナー&ステップアップ」というお題でしたが、がっつり SharePoint Framework についてお話させていただきました。実は勉強会で登壇するのは初めてで、10 分間の予定でしたが、かなり時間をオーバーしてしまい申し訳なかったです。次に話す機会があればもう少し精進したいですね。
スライドは Speaker Deck に公開しました。

また、デモに使ったサンプル コードは GitHub に上げてあります。

github.com
github.com

SharePoint 管理シェルで使用されている PipeBind オブジェクトについて

この記事は「PowerShell Advent Calendar 2017」の参加記事です。

qiita.com

SharePoint 管理シェルでは、例えば Get-SPWeb の Identity パラメーターに URL または ID (GUID) を渡すことができます。下記の例ではあえてキャストしていますが、もちろん文字列そのままを渡すこともできます。

$web1 = Get-SPWeb -Identity [uri]'http://server/sites/site'
$web2 = Get-SPWeb -Identity [guid]'909fb5bd-2ae3-4968-8ca6-b23f962d7300'

あるいは、SPWeb オブジェクトそのものを渡すこともできます。

$web3 = Get-SPWeb -Identity $web1

これがどのように実現されているかを見てみたいと思います。まずは Get-SPWeb のヘルプを見てみます。

docs.microsoft.com

Get-SPWeb
   [[-Identity] <SPWebPipeBind>]
   [-AssignmentCollection <SPAssignmentCollection>]
   [-Confirm]
   [-Filter <ScriptBlock>]
   [-Limit <String>]
   [-Regex]
   [-Site <SPSitePipeBind>]
   [-WhatIf]
   [<CommonParameters>]

Identity パラメーターの型は SPWebPipeBind です。PipeBind とはなんでしょうか。その答えは以下に説明があります。

SharePoint 管理シェル用コマンドレットの作成に関する重要な概念

PipeBind オブジェクトは、SharePoint 用の Windows PowerShell に固有の特別なオブジェクトであり、SharePoint Foundation 用に最適化された特殊なパラメーター セットという第 2 のレイヤーを提供します。

たとえば、SPSite パラメーターを取るコマンドレットは、SPSite オブジェクト自体を取ることも、そのサイト コレクションの GUID 識別子を取ることも、そのサイト コレクションの URL を取ることもできます。Windows PowerShell ランタイムによってどんな表現が与えられようとも、実際の SPSite オブジェクトがコマンドレット自体に間違いなく与えられるようにするのは、SPSitePipeBind オブジェクトの役目です。

つまり PipeBind オブジェクトがいい感じに受け皿となって、ユーザーが意識しなくても適切な表現として解釈してくれるというわけですね。この PipeBind オブジェクトのトリックは PowerShell の型変換の仕組みに依存しています。PowerShell は型変換をするときに、いくつかの手順で型変換を試みます。その中の手順のひとつである Constructor conversion により、元の値を渡してコンストラクターを呼び出してくれます。

blogs.msdn.microsoft.com

大事なのは、データの種類を型で判断しているので、同じ型のデータでは判断ができないことと*1、常に値が文字列で渡ってくる可能性を考慮することです。

ちなみに、同様の仕組みは、Active Directory モジュールなどにもあります。ただし、こちらは PipeBind という名前はついていません。例えば Get-ADUser の場合、インプットとアウトプットのどちらも ADUser です。個人的には SharePoint 管理シェルのように別の型になっていたほうが好みです。

*1:PnP-PowerShell の ContentTypePipeBind を見ると無理やり感が漂っています。