ASP.NET API 版本控制
ASP.NET API versioning
我是 ASP.NET 的新手,但我希望为新 API 实施一些版本控制,我即将开始。
我什至不确定我正在寻找的东西是否可行,但我正在寻找一种使用 header 变量的非常干净的版本方法。
理想情况下,我希望能够在代码结构中有一个版本文件夹,并在其中包含不同的 API 版本的不同文件夹。
每个版本文件夹都将包含核心 API 代码的完整副本,因此我知道永远不会有任何冲突等。我知道这会使代码膨胀,但值得保持它非常干净,并且只会有超过 2-3 个版本的 API 活跃。
我在 Internet 上找到了很多 header 示例,但它们都要求 类 位于不同的命名空间中,如果我正在复制代码的完整副本,那将是不切实际的每次复制时都必须重命名所有 类。
我想做的事情可行吗?或者在处理多个 类 时是否有更清晰的解决方案?
RESTful 版本有四种基本方法 -
URI 路径这种方法采用以下形式:
http://api/v2/Tasks/{TaskId}
URI 参数此方法采用以下形式:
http://api/Tasks/{TaskId}?v=2
内容协商这是在 HTTP header.
中完成的
内容类型:application/vnd.taskManagerApp.v2.param.json
请求Header HTTP中也是这样header.
x-taskManagerApp-version: 2
我个人喜欢第一种方法。您可以阅读Mike Wasson's ASP.NET Web API: Using Namespaces to Version Web APIs。
许多人修改了 Mike Wasson 的原始来源。我喜欢 ASP.NET Web API 2 book by Jamie Kurtz, Brian Wortman 中使用的那个。
由于动人的片段太多,我创作了a sample project at GitHub。
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{version}/{controller}",
defaults: new { version = "v2" }
);
config.Routes.MapHttpRoute(
name: "DefaultApiWithId",
routeTemplate: "api/{version}/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
然后,您添加 ApiVersionConstraint
public class ApiVersionConstraint : IHttpRouteConstraint
{
public ApiVersionConstraint(string allowedVersion)
{
AllowedVersion = allowedVersion.ToLowerInvariant();
}
public string AllowedVersion { get; private set; }
public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName,
IDictionary<string, object> values, HttpRouteDirection routeDirection)
{
object value;
if (values.TryGetValue(parameterName, out value) && value != null)
{
return AllowedVersion.Equals(value.ToString().ToLowerInvariant());
}
return false;
}
}
用法
您只需将 RoutePrefix 放在控制器上即可。
[RoutePrefix("api/{apiVersion:apiVersionConstraint(v1)}/values")]
public class ValuesController : ApiController
{
// GET api/v1/values
[Route("")]
public IEnumerable<string> Get()
{
return new string[] { "v1-value1", "v1-value2" };
}
// GET api/v1/values/5
[Route("{id}")]
public string Get(int id)
{
return "v1-value-" + id;
}
}
有点迟到的答案,但对于仍想将版本控制应用于 ASP.NET Web API 堆栈的任何人,ASP.NET API Versioning has become a very common way to achieve it. The Basic Sample 将带您完成所有必要的步骤以开始.
API 版本控制支持查询字符串、header、媒体类型和 URL 段 out-of-the-box。如果支持多个方法,则可以将方法组合在一起,甚至可以创建自己的方法来提取 API 版本。版本控制的默认方法是通过查询字符串。尽管它很受欢迎并且有@Win 的建议,但我 不 推荐按 URL 段进行版本控制。这是最少的 RESTful 方法,因为它违反了 统一接口 约束,并且存在大量有问题的边缘情况。
首先添加 ASP.NET Web API Versioning NuGet 包。您想要如何版本化以及如何组织代码是非常主观的,但这是一个非常准系统的设置:
namespace Example
{
public class WebApiConfig
{
public static Configure(HttpConfiguration config)
{
// TODO: this is the minimum, but there are many options that can be configured
config.AddApiVersioning();
// TODO: remaining configuration
}
}
// this is one of many possible ways you might organize controllers
namespace Controllers
{
namespace V1
{
[ApiVersion("1.0")]
[RoutePrefix("values")]
public class ValuesController : ApiController
{
// GET /values?api-version=1.0
[Route]
public IHttpActionResult Get(ApiVersion version) =>
Ok(new []{$"v{version}-Value1", $"v{version}-Value2"});
// GET /values/{id}?api-version=1.0
[Route("{id}")]
public IHttpActionResult Get(int id, ApiVersion version) =>
Ok($"v{version}-{id}")
}
}
namespace V2
{
[ApiVersion("2.0")]
[RoutePrefix("values")]
public class ValuesController : ApiController
{
// GET /values?api-version=2.0
[Route]
public IHttpActionResult Get(ApiVersion version) =>
Ok(new []{$"v{version}-Value1", $"v{version}-Value2"});
// GET /values/{id}?api-version=2.0
[Route("{id}")]
public IHttpActionResult Get(int id, ApiVersion version) =>
Ok($"v{version}-{id}")
}
}
}
}
我是 ASP.NET 的新手,但我希望为新 API 实施一些版本控制,我即将开始。
我什至不确定我正在寻找的东西是否可行,但我正在寻找一种使用 header 变量的非常干净的版本方法。
理想情况下,我希望能够在代码结构中有一个版本文件夹,并在其中包含不同的 API 版本的不同文件夹。 每个版本文件夹都将包含核心 API 代码的完整副本,因此我知道永远不会有任何冲突等。我知道这会使代码膨胀,但值得保持它非常干净,并且只会有超过 2-3 个版本的 API 活跃。
我在 Internet 上找到了很多 header 示例,但它们都要求 类 位于不同的命名空间中,如果我正在复制代码的完整副本,那将是不切实际的每次复制时都必须重命名所有 类。
我想做的事情可行吗?或者在处理多个 类 时是否有更清晰的解决方案?
RESTful 版本有四种基本方法 -
URI 路径这种方法采用以下形式:
http://api/v2/Tasks/{TaskId}
URI 参数此方法采用以下形式:
http://api/Tasks/{TaskId}?v=2
内容协商这是在 HTTP header.
中完成的内容类型:application/vnd.taskManagerApp.v2.param.json
请求Header HTTP中也是这样header.
x-taskManagerApp-version: 2
我个人喜欢第一种方法。您可以阅读Mike Wasson's ASP.NET Web API: Using Namespaces to Version Web APIs。
许多人修改了 Mike Wasson 的原始来源。我喜欢 ASP.NET Web API 2 book by Jamie Kurtz, Brian Wortman 中使用的那个。
由于动人的片段太多,我创作了a sample project at GitHub。
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{version}/{controller}",
defaults: new { version = "v2" }
);
config.Routes.MapHttpRoute(
name: "DefaultApiWithId",
routeTemplate: "api/{version}/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
然后,您添加 ApiVersionConstraint
public class ApiVersionConstraint : IHttpRouteConstraint
{
public ApiVersionConstraint(string allowedVersion)
{
AllowedVersion = allowedVersion.ToLowerInvariant();
}
public string AllowedVersion { get; private set; }
public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName,
IDictionary<string, object> values, HttpRouteDirection routeDirection)
{
object value;
if (values.TryGetValue(parameterName, out value) && value != null)
{
return AllowedVersion.Equals(value.ToString().ToLowerInvariant());
}
return false;
}
}
用法
您只需将 RoutePrefix 放在控制器上即可。
[RoutePrefix("api/{apiVersion:apiVersionConstraint(v1)}/values")]
public class ValuesController : ApiController
{
// GET api/v1/values
[Route("")]
public IEnumerable<string> Get()
{
return new string[] { "v1-value1", "v1-value2" };
}
// GET api/v1/values/5
[Route("{id}")]
public string Get(int id)
{
return "v1-value-" + id;
}
}
有点迟到的答案,但对于仍想将版本控制应用于 ASP.NET Web API 堆栈的任何人,ASP.NET API Versioning has become a very common way to achieve it. The Basic Sample 将带您完成所有必要的步骤以开始.
API 版本控制支持查询字符串、header、媒体类型和 URL 段 out-of-the-box。如果支持多个方法,则可以将方法组合在一起,甚至可以创建自己的方法来提取 API 版本。版本控制的默认方法是通过查询字符串。尽管它很受欢迎并且有@Win 的建议,但我 不 推荐按 URL 段进行版本控制。这是最少的 RESTful 方法,因为它违反了 统一接口 约束,并且存在大量有问题的边缘情况。
首先添加 ASP.NET Web API Versioning NuGet 包。您想要如何版本化以及如何组织代码是非常主观的,但这是一个非常准系统的设置:
namespace Example
{
public class WebApiConfig
{
public static Configure(HttpConfiguration config)
{
// TODO: this is the minimum, but there are many options that can be configured
config.AddApiVersioning();
// TODO: remaining configuration
}
}
// this is one of many possible ways you might organize controllers
namespace Controllers
{
namespace V1
{
[ApiVersion("1.0")]
[RoutePrefix("values")]
public class ValuesController : ApiController
{
// GET /values?api-version=1.0
[Route]
public IHttpActionResult Get(ApiVersion version) =>
Ok(new []{$"v{version}-Value1", $"v{version}-Value2"});
// GET /values/{id}?api-version=1.0
[Route("{id}")]
public IHttpActionResult Get(int id, ApiVersion version) =>
Ok($"v{version}-{id}")
}
}
namespace V2
{
[ApiVersion("2.0")]
[RoutePrefix("values")]
public class ValuesController : ApiController
{
// GET /values?api-version=2.0
[Route]
public IHttpActionResult Get(ApiVersion version) =>
Ok(new []{$"v{version}-Value1", $"v{version}-Value2"});
// GET /values/{id}?api-version=2.0
[Route("{id}")]
public IHttpActionResult Get(int id, ApiVersion version) =>
Ok($"v{version}-{id}")
}
}
}
}