2016-04-03 17 views
1

私はmvc6でバージョン管理されたAPIを作成しています。これを実行するには、動作するAPIバージョンのアクションを指定する必要があります。カスタム制約付きのMvc6のバージョン管理されたAPIアクション

私のAPIルートは/api/{version}/...です。したがって、特定のアクションでversionルート値を検査し、このアクションがそのバージョンで利用可能かどうかを確認します。

私は、例えばので、APIアクションの属性としてあることを指定できるようにしたい:私の質問はこれが動作するためにApiVersion実装または拡張する必要がありますものです

// This is the base api controller 
[Route("api/{version:regex(^v[[0-9]].[[0-9]]$)}/[controller]")] 
public abstract class ApiControllerBase { ... } 

// This is an action in one of the sub classes 
[HttpGet("foo")] 
[ApiVersion("0.1", "0.2")] // Here! (this is params string[]) 
public object Foo() 
{ 
    // return 
} 

// This is an action in another sub class 
[HttpGet("foo")] 
[ApiVersion("1.0")] 
public object Foo() 
{ 
    // return 
} 

?他のコントローラー内の他のアクションがこれを処理できるため、これが一致しないときに404を返すことを望まないため、アクションフィルターがうまく動作するとは思わない(後で私はHomeControllerの一般的なアクションとHome2Controller拡張アクションは1.0の場合のみ有効です)。私はApiVersionAttributeの実施を求めていないよ、私はちょうど私が私がという属性を作成できるようになる(アクションフィルタ、ルートの制約、...)にフックする必要があり、MVC何インフラを知る必要があり

ルート値を調べて、このアクションが一致するかどうかを判断できます。

+0

おそらく継承を使用して、別々のコントローラを持っていないのはなぜ?行動を扱うための属性を持っている私には、複雑なようです。行動が変わるとどうなるでしょうか? –

+0

どのアクションをどのバージョンに適用するかを照合する際には、多くの柔軟性が必要です。私が望むのと同じ柔軟性が達成できるならば、私は他の方法にもオープンです。それらのいくつかを今調べています。 – mrahhal

答えて

2

mvc6のソースを分析するのに4時間かかりましたが、それは価値がありました。私はMicrosoft.AspNet.Mvc.ActionConstraints.IActionConstraintを実装するアクション属性を使ってこれを解決しました。

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] 
public class ApiVersionAttribute : Attribute, IActionConstraint 
{ 
    public ApiVersionAttribute(string version) 
    { 
     Version = version; 
    } 

    public string Version { get; } 

    public int Order => 0; 

    public bool Accept(ActionConstraintContext context) 
    { 
     var routeData = context.RouteContext.RouteData; 
     // return ... 
    } 
} 

そして特定のアクションに:

[HttpGet("foo")] 
[ApiVersion("0.1")] 
public object Foo() 
{ 
    // return ... 
} 
関連する問題