使用IHttpControllerSelector进行AttributeRouting - Api版本控制

时间:2015-11-18 18:08:20

标签: asp.net asp.net-web-api attributerouting api-versioning

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

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

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

{{- form_widget(child, { 'attr': { 'my-attribute-name': 'my-value') } }) -}}
{{- form_widget(child, { 'attr': { 'my-attribute-name': attribute(attr, 'from-main-radio-form-element') } }) -}}

但正如我所知,当我在RoutePrefix(/ api / v2 / foo)上不使用完整网址时,属性路由没有启动,当我调用时我得到null

namespace Web.Controllers.Api.v2
{
    [RoutePrefix("foo")]
    public class LongerThanFooController : ApiController
    {
        [HttpGet]
        [Route("bar")]
        public string BarFunction()
        {
            return "foobar";
        }
    }
}
我的CustomHttpControlSelector上的

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

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

 request.GetRouteData().GetSubRoutes();

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

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

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

上的代码

1 个答案:

答案 0 :(得分:1)

我意识到这是一个老问题了,但是可以使用ASP.NET API VersioningASP.NET Web API包来回答。在最新的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("v{version:apiVersion}/foo/bar")]
    public string BarFunction()
    {
      return "foobar";
    }
  }
}

需要两个路由定义的原因是,不能在路由模板的中间设置默认值。默认值只能在末尾使用。这也意味着您无需指定任何API版本,并指出确定应选择哪个API版本的方法是使用当前实现(例如 latest )。我个人不喜欢这种方法,因为我认为客户应该可以预测事情的发展,但这将达到您期望的结果。