2

ASP.NETWebFormsアプリケーションの古いHttpHandlerAPIのメソッドをオーバーライドする必要がある状況があります。新しいAPIのベースとしてWebAPIを使用していますが、新しいAPIでアクションが見つからない場合にフォールバックするルーティングが必要なことを除けば、うまく機能しています。現在、これは当てはまりません。代わりに、WebAPIコントローラーに一致するアクションがない場合は常に「404:見つかりません」が表示されます。

新しいAPIのルーティングは次のとおりです。

var apiroute = routes.MapHttpRoute(
    "API Default",
    "api/{language}-{country}/{controller}/{action}/{id}",
    new { id = RouteParameter.Optional }
);

古いHttphandlerAPIは、次のようにルートを登録します(順序はWebAPIルートの後にあります)。

var route = new Route("api/{language}-{country}/Person/{command}", this);
RouteTable.Routes.Add(route);

Listアクションを持つPersonControllerがある場合は/api/ en-US / Person / Listを最初のルートに一致させ、ない場合は古いapiにフォールバックします。

質問:アクションが実際にコントローラーで使用可能な場合にのみ一致するように、最初のルートにフィルターを追加することは可能ですか?他にどのようにこれを達成できますか?

4

1 に答える 1

1

アップデート

属性ベースのルーティングを調査することもできます。これは、ルーティング属性で注釈を付けたアクションのみがルートに一致し、目的を達成するのに役立つ可能性がある、よりクリーンなソリューションになる可能性があります。

または

これよりも良い方法があるかもしれませんが、この記事IRouteConstraintなどのカスタムを実装すると可能です。

改善できる非常にラフで準備が整ったアプローチを以下に示します。

public class IfActionExistsConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        var actionName = values["Action"] as string;

        if (actionName == null)
        {
            return false;
        }

        var controllerName = values["Controller"] as string;
        var controllerTypeResolver = GlobalConfiguration.Configuration.Services.GetHttpControllerTypeResolver();
        var controllerTypes = controllerTypeResolver.GetControllerTypes(GlobalConfiguration.Configuration.Services.GetAssembliesResolver());
        var controllerType = controllerTypes.SingleOrDefault(ct => ct.Name == string.Format("{0}Controller", controllerName));

        if(controllerType == null)
        {
            return false;
        }

        return controllerType.GetMethod(actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) != null;
    }
}

登録:

var apiroute = routes.MapHttpRoute(
    name: "API Default",
    routeTemplate: "api/{language}-{country}/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional },
    constraints: new { IfActionExistsConstraint = new IfActionExistsConstraint() }
);
于 2012-12-14T11:08:10.533 に答える