最近は、サード パーティの MVC プラグインをホストできる ASP.NET MVC アプリケーションの作成に注力しています。理想的には、これらのプラグインの開発は次のルールに従います。
- プラグインは、標準の MVC プロジェクトで開発でき、ASP.NET MVC フレームワークの既存のインフラストラクチャをすべて使用できます。
- プラグイン MVC プロジェクトのコンパイルとホスト MVC アプリケーションへの組み込みの複雑さは深刻ではありません。
- MVC アプリケーションの通常の開発フローへの変更は最小限に抑えられます。
いくつかの調査の後、これを達成するための次のアプローチを思いつきました。それぞれに長所と短所があります。
アプローチ 1 - メイン MVC AppDomain にロードされた MVC プラグイン アセンブリ
ワークフロー
- 別の MVC プロジェクト内でプラグインを開発します。
- アセンブリをコンパイルし、ホスト プロジェクト内の
PreApplicationStartMethodAttribute
、MEF 、または基本的なアセンブリ参照 (可能な場合)を介して、アセンブリとすべての依存関係をホスト アプリケーションに読み込みます。 - プラグインがホスト内でとして扱われるように、ルートをプラグイン コントローラにマップし
Area
ます。 - プラグイン ビューを正しいエリア フォルダーに配置します。レイアウト ファイルは、レイアウト パスがアプリケーションのルートではなくエリア ベースの場所を指すように変更する必要があります (開発 MVC プロジェクトの場合)。
- プラグインに対する要求が届くと、ASP.NET は既存の領域機能を使用して要求を正しいコントローラーにルーティングし、ビュー ファイルの正しい場所を調べます。
利点
- コントローラーがホスト MVC アプリケーション アセンブリに埋め込まれているかのようにシームレスに動作します。
PreApplicationStartMethodAttribute
アプリケーションの開始前 ( 、プロジェクト参照) およびアプリケーションの開始後 ( MEF )に、アセンブリをホスト アプリケーション ドメインに簡単に含めることができます。
短所
- サンドボックスなし - コントローラーはホストと同じ信頼レベルになります。
結論
これは最も簡単な方法ですが、安全性も最も低くなります。これらのプラグインはホスト アプリケーションと同じ信頼レベルを持つため、信頼されていない開発者がプラグインを作成することを許可する可能性を本質的に排除します (つまり、ホスト アプリケーションが などのメソッドを実行できる場合System.IO.File.Delete
、プラグインも実行できます)。
アプローチ 2 - MAF を介して独自の AppDomain で実行される MVC プラグイン アセンブリ
このアプローチは、独自にサンドボックス化し、ライブラリAppDomains
を介してホストが使用できる MVC プラグインを作成できるようにすることを目的としています。System.Addin
構造
処理中の URL がプラグインを対象としているかどうかを判断するルートがホストに設定されます。などのパターンが考えられます。
example.com/p/{plugin}/{controller}/{action}/{id}
上記のパターンを持つすべてのルートは、モジュール ルーティング アクションを持つホスト コントローラーにマップされます。そのアクションは、特定のルートを調べて、
{plugin}
セグメントに基づいてリクエストを処理する適切なプラグインを決定します。プラグイン ビューは、プラグイン コントローラーへのゲートウェイとして機能するレシーバー/センダー オブジェクトです。ホストからを受け取り、を返すAcceptRequestというメソッドがあります。
RequestContext
ActionResult
プラグイン パイプラインには、パイプラインの分離境界を越えてシリアル化
RequestContext
および送信できるアダプターが含まれています。ActionResult
実行の流れ
プラグインのルートが照合され、プラグイン ルーティング コントローラーが呼び出されます。
コントローラーは、必要なプラグインを独自のプラグインにロードし、AcceptRequest
AppDomain
を呼び出して(パイプライン経由でシリアル化されます) を通過します。RequestContext
AcceptRequestはコンテキストを受け取り、その要求に基づいて実行する適切なコントローラーを決定します (カスタム コントローラー ファクトリを使用)。
コントローラがリクエストの実行を完了すると、レシーバ オブジェクトに が返さ
ActionResult
れ、レシーバ オブジェクトはそれをActionResult
(これもパイプライン経由でシリアル化されて) ホストに戻しますAppDomain
。最初にAcceptRequest
ActionResult
を呼び出したコントローラーは、要求自体を処理したかのように、ホスト MVC 実行パイプラインに を返すことができます。その後、必要に応じてプラグインAppDomain
をアンロードできます。
利点
プラグインは でサンドボックス化されるAppDomain
ため、ホストに適した任意の権限セットを使用できます。
短所
- シリアル化
RequestContext
およびActionResult
. - 分離された 内の他の ASP.NET MVC 機能が壊れる可能性があります
AppDomain
。
結論
このアプローチは紙の上では良さそうに思えますが、オブジェクトRequestContext
とActionResult
オブジェクトをシリアル化し、MVC コントローラーを分離して実行することが可能/実行可能かどうかはわかりません。
質問
コードが信頼できる開発者によって作成されている場合は、最初の方法で問題ありません。すべてのホスト ビュー ファイルまたは web.config ファイルを削除するつもりはないことはわかっています。しかし最終的に、サード パーティの開発者に MVC アプリ用のプラグインを作成してもらいたい場合は、サード パーティのコードをサンドボックス化できる必要があります。
私のすべての調査によると、System.Addin
単純な API ベースのクラス ライブラリを使用している場合、このライブラリを使用すると、ホスト/プラグイン環境を簡単に実装できます。しかし、MVC が関係する場合、これを行うのは容易ではないようです。
私が持っているいくつかの質問は次のとおりです。
- ここで概説した 2 番目のアプローチは実行可能ですか?
- これを行うより良い方法はありますか?
- 将来、MVC プラグインの分離を実現するためのより簡単な方法はありますか?