带有 IHttpControllerSelector 的 AttributeRouting - Api 版本控制

Posted

技术标签:

【中文标题】带有 IHttpControllerSelector 的 AttributeRouting - Api 版本控制【英文标题】:AttributeRouting with IHttpControllerSelector - Api Versioning 【发布时间】:2016-02-20 14:39:34 【问题描述】:

我正在尝试在 asp.net webapi 上使用 CustomHttpControlSelector 和 AttributeRouting 来实现 api 版本控制。

我想要做的是通过它的命名空间来区分控制器的版本。

如果向 /api/v2/foo/bar 发出请求 我希望它匹配

namespace Web.Controllers.Api.v2

    [RoutePrefix("foo")]
    public class LongerThanFooController : ApiController
    
        [HttpGet]
        [Route("bar")]
        public string BarFunction()
        
            return "foobar";
        
    

但是正如我看到的,当我不在 RoutePrefix (/api/v2/foo) 属性上使用完整的 url 时,属性路由不会启动,当我调用时我得到 null

 request.GetRouteData().GetSubRoutes();

在我的 CustomHttpControlSelector 上。我不想在每个控制器上重复 /api/v2。

如果我决定删除 attributeRouting 并使用手动路由,例如

 config.Routes.MapHttpRoute(
         name: "DefaultVersionedApi",
         routeTemplate: "api/vversion/controller/id",
         defaults: new  id = RouteParameter.Optional 
 );

 config.Routes.MapHttpRoute(
          name: "DefaultApi",
          routeTemplate: "api/controller/id",
          defaults: new  id = RouteParameter.Optional, version = Config.LatestVersion 
  );

我失去了命名控制器和函数的所有灵活性。

有没有办法摆脱这种困境?

注意:对于 CustomHttpControlSelector,我在 http://aspnet.codeplex.com/SourceControl/changeset/view/dd207952fa86#Samples/WebApi/NamespaceControllerSelector/NamespaceHttpControllerSelector.cs 上修改了代码

【问题讨论】:

【参考方案1】:

我现在意识到这是一个老问题,但可以使用ASP.NET Web API 的ASP.NET API Versioning 包来回答。在最新的 3.0 版本中,您可以通过更新配置来实现您的方案:

var constraintResolver = new DefaultInlineConstraintResolver()

  ConstraintMap =
  
    ["apiVersion"] = typeof( ApiVersionRouteConstraint )
  
;

configuration.AddApiVersioning(
  options =>
  
    options.Conventions.Add( new VersionByNamespaceConvention() );
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.ApiVersionSelector = new CurrentImplementationApiVersionSelector( options );
   );

configuration.MapHttpAttributeRoutes( constraintResolver );

您还应该删除基于约定的路线。如果您使用属性路由,则这些都是不必要的。

您的控制器的设置只需更改为:

namespace Web.Controllers.Api.v2

  [RoutePrefix("api")]
  public class LongerThanFooController : ApiController
  
    [HttpGet]
    [Route("foo/bar")]
    [Route("vversion:apiVersion/foo/bar")]
    public string BarFunction()
    
      return "foobar";
    
  

您需要两个路由定义的原因是您不能在路由模板的中间有默认值。默认值只能在最后使用。这也意味着您需要不允许指定任何 API 版本,并指示确定应选择哪个 API 版本的方法是使用当前实现(例如 最新)。我个人不喜欢这种方法,因为我认为事情对客户来说应该是可预测的,但这会达到你想要的结果。

【讨论】:

以上是关于带有 IHttpControllerSelector 的 AttributeRouting - Api 版本控制的主要内容,如果未能解决你的问题,请参考以下文章

带有和不带有聚合的 sql 查询

如何翻转正面带有标签而背面带有另一个标签的视图 - 参见图片

CakePHP 如何处理带有/不带有 'id' 字段的 HABTM 表?

带有滚动的 Div 和带有绝对位置的内容

带有 RecyclerView 的 DialogFragment 比带有 Recyclerview 的 Fragment 慢

访问控制允许带有和不带有 www 的来源