2016-04-03 3 views
1

Ich mache eine versionierte API mit MVC6 und dazu möchte ich in der Lage sein, für eine Aktion anzugeben, auf welcher API-Version es funktionieren sollte.Mvc6 versionierte API-Aktionen mit benutzerdefinierten Einschränkungen

Meine api Route ist: /api/{version}/... und so möchte ich bei einer bestimmten Aktion die version Route Wert prüfen und sehen, ob diese Aktion für diese Version verfügbar ist.

Ich möchte auf der api Aktion, das als ein Attribut festlegen können, so zum Beispiel:

// 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 
} 

Meine Frage, was ApiVersion für diese implementieren oder erweitern soll, ist zu arbeiten? Ich glaube nicht, dass Aktionsfilter so funktionieren, wie ich es möchte, weil ich kein 404 zurückgeben möchte, wenn dies nicht passt, weil andere Aktionen in anderen Controllern dazu in der Lage sind. Später habe ich vielleicht HomeController mit gemeinsamen Aktionen und Home2Controller mit erweiterten Aktionen, die nur für 1.0 funktionieren).

Hinweis, dass ich nicht für eine Implementierung von ApiVersionAttribute fragen, ich muss nur wissen, was mvc Infrastruktur I in (Aktionsfilter, Routen Einschränkungen, ...) haken sollte, das mir ein Attribut erstellen lassen, dass kann in Routenwerte schauen und sagen, ob diese Aktion eine Übereinstimmung ist.

+0

Warum haben keine separaten Controller, vielleicht Vererbung? Für mich scheint es kompliziert zu sein, Attribute zu haben, um mit Aktionen umzugehen. Und was ist, wenn sich eine Handlung ändert? –

+0

Ich möchte wirklich nur eine Menge Flexibilität haben, wenn es darum geht, welche Aktionen für welche Versionen gelten. Ich bin offen für andere Methoden, wenn die von mir gewünschte Flexibilität erreicht werden kann. Einige davon jetzt erforschen. – mrahhal

Antwort

2

Es dauerte 4 Stunden die Analyse der mvc6 Quelle, aber es hat sich gelohnt. Ich löste das mit einem Aktionsattribut, das Microsoft.AspNet.Mvc.ActionConstraints.IActionConstraint implementiert.

[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 ... 
    } 
} 

und dann auf einer bestimmten Aktion:

[HttpGet("foo")] 
[ApiVersion("0.1")] 
public object Foo() 
{ 
    // return ... 
}