2014-03-24 9 views
5

Ich versuche, ein WCF/REST-Dienstprojekt in MVC/WebAPI zu konvertieren. Die Service-Schicht wird mehrfach als Wrapper für verschiedene Endsysteme implementiert, und alle Implementierungen beobachten einen allgemeinen Vertrag, der in einer Schnittstelle definiert ist (IContract). Mit WCF definierten wir [WebInvoke] und [OperationContract] Attribute für jede der Methoden, die als Web-Service-Methoden zur Verfügung gestellt wurden. In WebAPI kann dies vereinfacht werden, indem das Attribut-Routing auf dem Controller definiert wird. Ich möchte jedoch die Routenattribute für die Schnittstelle beibehalten, sodass sich alle Implementierungen ähnlich verhalten.WebApi-Attribut-Routing, das auf der Schnittstelle definiert ist

Hier ist ein Beispiel der alten Schnittstelle:

[ServiceContract] 
public interface IContract 
{ 
    [WebInvoke(UriTemplate = "Version", Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)] 
    [OperationContract] 
    string GetVersion(); 
} 

Hier ist, was ich habe gehofft, zum Laufen zu bringen:

public interface IContract 
{ 
    [Route("Version")] 
    [HttpGet] 
    string GetVersion(); 
} 

ich auch eine abstrakte Basisklasse zu schaffen, aber diese anderen StackOverflow question Marken in Betracht ziehen würde Ich denke, es gibt keinen geeigneten Ersatz für [WebInvoke(UriTemplate)] mit WebAPI-Attribut-Routing. Ist das der Fall oder kann mich jemand auf eine ähnliche unterstützte Technik hinweisen?

Dank

Antwort

1

Sie die Schnittstelle mit einem Attribut Route nicht dekorieren können. Dies liegt daran, dass die Web-API in ihrem eigenen Framework funktioniert ... Sie prüft alle Objekte vom Typ ApiController, um zu bestimmen, was zu routen ist. Es fragt grundsätzlich die Attribute Ihrer eigenen Controller-Methoden ab, um das Routing zu erstellen. Es sucht nicht nach Ihrer benutzerdefinierten IContract Schnittstelle, so dass es nicht so ein Routing tun würde.

Auch wenn Sie die Code-Basis der Web API ändern, um Route Attribute von Schnittstellen zu lesen und zu verarbeiten, wie würde das funktionieren? Eine Schnittstelle ist ein Vertrag und enthält keine Funktionalität. Also, wenn es eine Route für "Version" sah, welche Controller-Implementierung/Instanz würde es zuordnen? Die erste, die es willkürlich findet, die IContract zugewiesen werden kann? Der Letzte? Alle von ihnen? Und wenn alle von ihnen, wie führen Sie N-Controller-Methoden auf einmal aus?

Ich glaube, Sie müssen Ihr Verständnis von Attribut-Routing zu bewerten. Er weist das Web-API-Framework an, diese Methode auf diesem Controller für diese Route zu verwenden. Sie konnten dies nicht zur Schnittstelle abstrahieren, da es nicht in der Lage wäre zu bestimmen, welche abgeleitete Klasse ausgeführt werden soll.

+1

Während das ist eine ganz vernünftige Erklärung, die ich mit einigen, ich denke, es ist überraschend, dass WCF REST einen sehr ähnlichen Ansatz durch die Verwendung von '[WebInvoke (UriTemplate)] unterstützt' auf Schnittstellen platziert Attributen. Eine bessere Struktur wäre wahrscheinlich, eine abstrakte Basisklasse mit den Routenattributen zu implementieren, und es sieht so aus, als ob Version 5.2 der Web-API dieses Szenario unterstützen sollte (siehe [diese aktualisierte Antwort] (http://stackoverflow.com/a/19989344/). 44770)) – tbetts42

+0

Ich höre Sie auf der WCF REST, aber ich persönlich fühle, dass es SOLID Prinzipien bricht. Wenn ich die Schnittstelle kenne, um Klassen zu implementieren, vereitelt das den Zweck - zumindest in meinen Augen. – Haney

4

Nach ein paar mehr Forschung in was aus dem ASP.NET-Team kommt, sieht es aus wie die System.Web.Http.Routing.IDirectRouteProvider Erweiterbarkeit wird hoffentlich unsere Bedürfnisse erfüllen. Zum jetzigen Zeitpunkt ist dies nur mit den nächtlichen Builds von ASP.NET möglich, wird aber hoffentlich RTM oder zumindest CTP erreichen, sobald wir bereit sind, es zu veröffentlichen.

Der folgende Code zeigt, wie dies oben (Quelle: https://aspnetwebstack.codeplex.com/workitem/1464) für mein Beispiel implementieren

In Application_Start oder WebApiConfig.Register() ein neues IDirectRouteProvider zur MapHttpAttributeRoutes() Methode übergeben.

config.MapHttpAttributeRoutes(new CustomDirectRouteProvider()); 

Definieren Sie den Routenanbieter wie folgt. Dies aktiviert im Grunde nur die Attributvererbung, so dass es Routen von der Basisklasse (aber nicht von der Schnittstelle) liest.

public class CustomDirectRouteProvider : DefaultDirectRouteProvider 
{ 
    protected override IReadOnlyCollection<IDirectRouteFactory> GetActionRouteFactories(HttpActionDescriptor actionDescriptor) 
    { 
     return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(inherit: true); 
    } 
} 

In meinem Fall haben wir einen abstrakten BaseApiController der [Route] Attribute die WebAPI Methoden zur Verfügung stellt.

public abstract class BaseApiController : ApiController, IContract 
{ 
    [Route("Version")] 
    [HttpGet] 
    public abstract string GetVersion(); 

} 

Unsere Endsysteme waren früher WCF REST-Dienstendpunkte, die eine IContract-Schnittstelle implementierten. Für WebAPI werden die Controller jetzt vom BaseApiController abgeleitet. (Wir mussten auch den Namen von ContractService zu ContractServiceController ändern.) Wir hielten IContract für Rückwärtskompatibilität bereit, aber es ist jetzt auf BaseApiController implementiert. Das Attribut [RoutePrefix] ist auf dem Controller definiert, was in diesem Fall unsere Stamm-URL ist.

[RoutePrefix("")] 
public class TestController : BaseApiController 
{ 
    public override string GetVersion(); 
    { 
     return "Version 1.0.0.0"; 
    } 
} 
Verwandte Themen