JavaScript REST APIを使用して、SharePoint 2013プロバイダーホストアプリを開発しています。共有アイテムで作成(POST)または更新(MERGE)操作を実行するには、リクエストに「X-RequestDigest」ヘッダーを設定する必要があります。
SharePointでホストされるアプリでは、 http://contoso.sharepoint.com/SharePointHostedApp/_api/contextinfo サービスを使用して、リクエストダイジェスト値を取得できました。ただし、プロバイダーがホストするアプリでその値を取得するのに問題があります。
プロバイダーホスト型アプリの最初の違いは、SharePointサイトではなく、別のサーバーでホストされている別のドメインで実行しているため、クロスドメインリクエストを行う必要があることです。明確にする:代わりに
_$.ajax({
url: appWebUrl + '/_api/contextinfo',
method: "POST",
headers: { "Accept": "application/json; odata=verbose" }
})
_
クロスドメインリクエストを実行するには_SP.RequestExecutor
_を使用する必要があると想定しました。リクエストを作成すると、次のようになります(実際のURLを偽に変更しましたが、基本的には、ホストWebを使用してターゲットを持ち、_/_api/contextinfo
_エンドポイントを取得するようにプロキシに指示しています):
https://contoso-6f921c6addc19f.sharepoint.com/ProviderHostedApp/_api/SP.AppContextSite(@target)/contextinfo?@target=%27https://contoso.sharepoint.com%27
ただし、このエラーが表示されます:_Cannot find resource for the request contextinfo.
_は、エンドポイントが存在しないことを意味します。
空のボディを持つ正しい_application/json;odata=verbose
_ヘッダーでPOSTメソッドを使用するようにしました。
_/_api/contextinfo
_サービスからプロバイダーホスト型アプリへのリクエストダイジェスト値を取得するにはどうすればよいですか?
私が研究したことに基づいて:
$('#__REQUESTDIGEST').val()
;は使用できません。プロバイダーがホストするアプリでは利用できないためです。この値を取得するには何らかの方法が必要です。そうしないと、JavaScriptを使用するときに読み取り操作のみに制限されます。 他の誰かがjavascriptを使用してこれを解決しましたか?
技術的には、サーバー上のCSOMを使用して必要なサービスを実装し、WebAPIまたはWCFを使用してそれらを公開しようとすることができますが、それを実装しなければならないのは不合理に思えます。
UPDATE:
先に進み、リクエストダイジェスト値を取得するサービスを公開するWebAPIコントローラーを追加してみました。これは実際に要求ダイジェスト値を取得します。ただし、今後の呼び出しのヘッダーでこれを使用しようとすると、エラーが表示されます。_"The security validation for this page is invalid and might be corrupted. Please use your web browser's Back button to try your operation again."
_要求ダイジェスト値には、サーバーによって要求されたことを示すリファラーヘッダー情報が含まれていると推測しています。ただし、今後行われるリクエストはブラウザからのものであり、この不一致が無効になる理由として受け入れられる場合があります。
WebAPIコントローラーを追加しようとする試みについて、もう少し注意してください。この例に基づいてコードを作成しました: http://code.msdn.Microsoft.com/SharePoint-2013-Perform-335d925b が、新しいHttpClientを使用するように変換しました。 Page_Loadメソッドをオーバーロードし、WebAPIコントローラーがアクセスできる変数にcontextTokenStringを格納し、contextinfoを要求するときにそれを解析/使用しました。
これがそのエラーの正しい診断であるかどうかは誰にもわかりますか?リクエストダイジェスト値にエンコードされたものがあり、それが私が提案したように取得できないようにしますか?
また、MSDNフォーラムで関連する質問を開いています。答えを見つけるために必死だからです。 http://social.msdn.Microsoft.com/Forums/sharepoint/en-US/f601fddd-3747-4152 -b2d1-4e89f0a771c4/provider-quest-about-limitation-of-providerhosted-apps-is-it-possible-to-make-rest-calls-with-javascript?forum = sharepointdevelopmentprevious
これがプロバイダーがホストするアプリケーションの制限であると信じることは非常に難しいと思いますが、私が行ったすべてのテストを考えると、javascriptで書きたいときにプロバイダーがホストするアプリケーションの実行可能性を疑い始めています。
助けを求めて!
許可レベルには、_apiの下のすべてのサービスを無効にするチェックが存在することを覚えていますか
_api/web/lists _api/search/query?querytext = ’SharePoint’ _api/SP.UserProfiles.PeopleManager
有効にすることを確認します
サイトの設定->サイトの権限->権限レベル->読み取り->
統合クライアント機能リモートインターフェイスを使用
https://letrasandnumeros.com/2017/02/28/unauthorizedaccessexception-sharepoint-_api/ で解決策を見つけました
RequestExecutorは、実際にRequestDigestを処理します。取得する必要はありません。
何らかの理由でRequestDigest値を取得したい場合は、コンテキストサイトを変更せずに呼び出しを実行してください。
さて、問題を再テストするために、プロバイダーでホストされる新しいアプリケーションを作成しました。
ここでリポジトリを表示できます。
https://github.com/mattmazzola/providerhosted_01
この新しいアプリケーションと古いアプリケーションを比較した後、私はSP.RequestExecutorがどのようにURLを構築するのかを誤解していることに気付きました。 SP.AppContextSite()エンドポイントを使用する必要があると思いました。
次のようなURLでappWebへのリクエストを誤って作成していました。
ご覧のとおり、@ targetはappWebのURLに設定されていますが、RequestExecutorを使用してappWebにリクエストを行う際には、これを行う必要はありません。それは単にappweburl + "/ _api/contextinfo"です。 AppContextSiteを使用して@targetを設定する必要があるのは、hostWebに存在するリソースに対してリクエストを行う場合のみです。
詳細については、リンクされたソリューションの完全なコードをご覧ください。ソリューションのスクリーンショットを追加しました。