界面

2014-03-24 74 views
5
上定義的WebApi屬性路由

我試圖將WCF/REST服務項目轉換爲MVC/WebAPI。服務層多次作爲不同終端系統的包裝實現,並且所有實現遵守界面中定義的通用契約(IContract)。在WCF中,我們定義了作爲Web服務方法公開的每種方法的[WebInvoke][OperationContract]屬性。在WebAPI中,這可以通過在控制器上定義的屬性路由來簡化。但是,我想保留接口上定義的路由屬性,因此所有實現的行爲都相似。界面

這裏的老界面的樣本:

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

這是我希望得到的工作:

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

我也會考慮創建一個抽象基類,但這其他StackOverflow question品牌我認爲沒有合適的替代[WebInvoke(UriTemplate)]使用WebAPI屬性路由。是這種情況,還是有人可以指點我一個類似的支持技術?

感謝

回答

1

不能裝飾用Route屬性界面。這是因爲Web API在其自己的框架內工作......它檢查所有類型爲ApiController的對象以確定要路由的內容。它基本上會詢問您的自定義控制器的方法屬性以創建路由。它不尋找你的自定義接口,所以它不會在意這樣的路由。

即使您更改Web API的代碼庫以從接口讀取和處理Route屬性,這將如何工作?接口是一個契約,不包含功能。那麼,如果它看到一條"Version"的路由,它會將它映射到哪個控制器實現/實例?第一個它任意發現哪些可以分配到IContract?最後一個?他們全部?如果他們都是,那麼你如何一次執行N個控制器方法?

我相信你需要評估你對屬性路由的理解。它告訴Web API框架在THIS控制器上爲THIS路徑使用THIS方法。您無法將其抽象爲接口,因爲它無法確定要執行的派生類。

+1

雖然這是我同意一個完全合理的解釋,我想這是令人驚訝的是WCF REST支持的一個非常類似的方法通過使用'[WebInvoke(UriTemplate)]'放置在接口屬性。更好的結構可能是使用路由屬性實現抽象基類,並且它看起來像Web API的5.2版本應該支持這種情況(請參閱[更新的答案](http://stackoverflow.com/a/19989344/) 44770)) – tbetts42

+0

我在WCF REST上聽到你的聲音,但我個人覺得它打破了SOLID原則。讓界面知道如何實現類實現了目的 - 至少在我眼中。 – Haney

4

經過對來自ASP.NET團隊的更多研究後,它看起來像是可擴展性將有望滿足我們的需求。截至撰寫本文時,這隻能使用ASP.NET每晚構建,但在我們準備推出時,希望可以達到RTM或至少CTP。

下面的代碼顯示如何實現此我的例子上述(原始來源:https://aspnetwebstack.codeplex.com/workitem/1464

Application_StartWebApiConfig.Register()傳遞一個新IDirectRouteProviderMapHttpAttributeRoutes()方法。

config.MapHttpAttributeRoutes(new CustomDirectRouteProvider()); 

定義Route Provider如下。這基本上只是打開屬性繼承,所以它會從基類(但不是接口)讀取路由。

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

在我的例子中,我們創建了一個抽象的BaseApiController提供[Route]屬性到的WebAPI的方法。

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

} 

我們的最終系統是以前WCF REST服務端點其中實現的IContract接口。對於WebAPI,控制器現在從BaseApiController派生。 (我們還必須將ContractService的名稱更改爲ContractServiceController。)爲了向後兼容,我們保留了IContract,但現在它已在BaseApiController上實現。控制器上定義了[RoutePrefix]屬性,在這種情況下,它是我們的根URL。

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