2016-04-22 93 views
1

我一直在使用WebApi,並試圖瞭解如何使用Route Attribute與具有WebApi的差異自動創建基於函數名稱作品的路由。我有這種形式的許多控制器:WebApi使用RouteAttribute或隱式路由時的路徑差異

public class MyController : RestControllerBase 
{ 
    public async Task<HttpResponseMessage> GetData() 
    { 
     return _data; 
    } 

    [Route(ApiVersion.Version + "/MyController/{param}/specific/route")] 
    public async Task<HttpResponseMessage> GetMoreData() 
    { 
     return _moreData; 
    } 
} 

該控制器和其他所有指定的路線註冊表,做:

routingManager.RegisterVersionedHttpRoute(
       routeName: "MyController", 
       routeTemplate: "MyController/{param}", 
       defaults: new { controller = "MyController", param = RouteParameter.Optional }, 
       version: ApiVersion.Version); 

當我建立和測試我的API,兩個端點都正確地訪問。

我也用一個基於命名空間(用於版本控制)覆蓋HttpControllerSelector。

我的問題是除了被特定的http路由調用的傳統函數之外,這兩個路由的行爲不同。例如,在我重寫的控制器選擇我不得不爲了使控制器和路線正確映射寫這個邏輯:

private string GetControllerName(IHttpRouteData routeData) 
{ 
    if (routeData.GetSubRoutes() != null) 
    { 
     // With route attribute 
     var subroute = routeData.GetSubRoutes().FirstOrDefault(); 
     var dataTokenValue = subroute.Route.DataTokens["actions"]; 
     if (dataTokenValue == null) return null; 
     var controllername = ((HttpActionDescriptor[])dataTokenValue).First().ControllerDescriptor.ControllerName.Replace("Controller", string.Empty); 
     return controllername; 
    } 
    else 
    { 
     // Try Strategy for without route attribute. 
     return (String)routeData.Values["controller"]; 
    } 
} 

private string GetVersion(IHttpRouteData routeData) 
{ 
    var routeTemplate = ""; 
    if (routeData.GetSubRoutes() != null) 
    { 
     var subRouteData = routeData.GetSubRoutes().FirstOrDefault(); 
     if (subRouteData == null) return null; 
     routeTemplate = subRouteData.Route.RouteTemplate; 
    } 
    else 
    { 
     routeTemplate = routeData.Route.RouteTemplate; 
    } 

    var index = routeTemplate.IndexOf("/"); 
    if (index == -1) 
    { 
     return Unversioned; 
    } 
    var version = routeTemplate.Substring(0, index).ToUpperInvariant(); 
    return version; 
} 

這好像與明確的屬性的路由將有route.GetSubroutes()可用,而隱式路線則不會。 這使我可以編寫兩種不同的方法來從傳入的請求中提取版本和控制器名稱,然後才能正確路由它們。我可以忍受這一點,但是真的讓我困擾,WebApi內部的某些東西正在創造這種路線之間的區別。

不幸的是,我開始使用https://github.com/domaindrivendev/Swashbuckle來記錄我的api並遇到類似的問題。對於具有Route屬性但完全忽略隱式路由的路由,正確的生成頁面生成頁面。我懷疑造成這個問題的問題與我選擇邏輯中的分支相同。

我一直在挖掘儘可能多的ApiExplorer,WebAPI和其他文檔,因爲我可以在網上找到,但我一直無法找到解決方案來均一化隱式/顯式路由方法。它甚至可能是它們實現中的一個錯誤。

我應該從哪裏出發?

回答

0

所以這裏的答案是,有一個錯誤或不一致的Web Api 2 要驗證,您可以運行此代碼段。在我提到的情況下,ApiExplorer不返回沒有用路由屬性明確標記的路徑的結果。

 IApiExplorer apiExplorer = configuration.Services.GetApiExplorer(); 
     foreach (ApiDescription api in apiExplorer.ApiDescriptions) 
     { 
      Console.WriteLine("Uri path: {0}", api.RelativePath); 
      Console.WriteLine("HTTP method: {0}", api.HttpMethod); 
      foreach (ApiParameterDescription parameter in api.ParameterDescriptions) 
      { 
       Console.WriteLine("Parameter: {0} - {1}", parameter.Name, parameter.Source); 
      } 
      Console.WriteLine(); 
     }