1

ASP.NET MVCを使用してCMSを作成していますが、設計上、各プラグイン(アドオン)が着信HTTP要求にキーを持つ必要があると判断しました。したがって、ホストアプリケーションには次の一般的なルートがあります。

{pluginKey}/{controller}/{action}/{id}

を実装するカスタムコントローラーファクトリを作成しました。IControllerFactoryもちろん、ReqeustContextコントローラー名に基づいてコントローラーを作成するメソッドがあります。ただし、プラグインのコントローラーがこれらのURLセグメントを誤って解釈しないように、(HttpRequest、RequestContext、RouteDataなどの他のすべての関連オブジェクトとともに)人工的なHttpContextを作成したいと思います。つまり、受信URLの最初の部分を切り取り、プラグインにこのURLを処理していると思わせるようにします。

{controller}/{action}/{id}

どうすればこれを達成できますか?

4

1 に答える 1

3

すべてのコンテキスト クラスの新しい実装を作成することもできますが、少しやり過ぎのように思えます。HttpHandler を返す前にフィルタリング機能を適用する派生ルート ハンドラーを使用しないのはなぜですか? 次に例を示します。

//  To avoid conflicts with similarly named controllers, I find it to be good practice
//  to create a route constraint with the set of all plugin names.  If you don't have 
//  this function already, you should be able to access it with reflection (one time 
//  per app lifecycle) or you hard-code them.  The point is to have a regex which ensures
//  only valid plugins will get selected
string[] pluginNames = GetPluginNames();
string pluginNameRegex = string.Join("|",pluginNames);

Route pluginRoute = new Route (
    url: "{pluginKey}/{controller}/{action}/{id}",
    defaults: null,
    constraints: new RouteValueDictionary(new { pluginKey = pluginNameRegex }),
    routeHandler: new PluginRouteHandler()
});

//  The custom route handler can modify your route data after receiving the RequestContext 
//  and then send it to the appropriate location.  Here's an example (markdown code/untested)
//  Note: You don't have to inherit from MvcRouteHandler (you could just implement IRouteHandler
//  but I'm assuming you want Mvc functionality as the fallback)
public class PluginRouteHandler : MvcRouteHandler 
{ 
    public PluginRouteHandler(IControllerFactory controllerFactory) 
      : base(controllerFactory)
    {}

    protected override IHttpHandler GetHttpHandler(RequestContext requestContext){
        if(ValidatePluginRoute(requestContext)) 
        {
           //  we are going to remove the pluginKey from the RequestContext, It's probably wise
           //  to go ahead and add it to HttpContext.Items, in case you need the data later
           requestContext.HttpContext.Items["pluginKey"] = requestContext.RouteData.Values["pluginKey"];

           //  now let's get ride of it, so your controller factory will process the 
           //  requestContext as you have described.
           requestContext.Values.Remove("pluginKey");

           //  the route will now be interpreted as described so let the flow go to the MvcRouteHandler's method
        }
        return base.GetHttpHandler(requestContext);
    }
    static bool ValidatePluginRoute(RequestContext requestContext){
        return requestContext.RouteData.ContainsKey("pluginKey");
    }
}
于 2012-06-06T08:22:47.763 に答える