ASP.NET
Core Web
API Versioning
▌Introduction
This
article shows how to support API versioning on ASP.NET Core Web API.
▌Environment
▋.NET Core 2.2.104
▋Visual Studio 2017 Community
▌Implement
▋Install Packages
▋Enable Versioning
In Startup.cs,
public void
ConfigureServices(IServiceCollection services)
{
//
ApiVersioning
services.AddApiVersioning(opt
=>
{
opt.ReportApiVersions = true; // List
supported versons on Http header
opt.DefaultApiVersion
= new ApiVersion(1, 0); // Set the
default version
opt.AssumeDefaultVersionWhenUnspecified
= true; // Use the api of default version
opt.ApiVersionSelector = new CurrentImplementationApiVersionSelector(opt); // Use the
api of latest release number
});
}
Results:
HTTP/1.1 200 OK
api-supported-versions: 1.0
The DefaultApiVersion
can has a postfix like this,
opt.DefaultApiVersion = new ApiVersion (2, 1, "awesome");
Which
will results in the header of http response:
HTTP/1.1 200 OK
api-supported-versions: 2.1-awesome
▋Multiple version for same API
We can have
the API in 2 versions with different Action names.
[HttpGet("Get")]
[ApiVersion("1.0")]
public ActionResult<IEnumerable<string>> Get()
{
return new
string[] { "Version", "v1.0" };
}
[HttpGet("Get")]
[ApiVersion("2.0")]
public ActionResult<IEnumerable<string>> GetV2()
{
return new
string[] { "Version", "v2.0" };
}
Or create
them within different namespaces
with the same Action name.
▋Request without specified version
▋Request without
specified version
Any http
requests without specified version will use the API of default version.
Notice if no API matches the
default version specified at
1. opt.DefaultApiVersion
= new ApiVersion (...);
2. [ApiVersion("...")]
An Bad Request(400) will be returned like following,
HTTP/1.1 400 Bad Request
api-supported-versions: 1.0, 2.0
{"error":{"code":"UnsupportedApiVersion","message":"The
HTTP resource that matches the request URI
'http://localhost:5000/api/Demo/Get' is not
supported.","innerError":null}}
|
▋By URI Parameter
Use the
following Uri parameter to specify the target version:
api-version=<version_number>
For
example,
http://localhost:5000/api/Demo/Get?api-version=1
http://localhost:5000/api/Demo/Get?api-version=2
http://localhost:5000/api/Demo/Get?api-version=2.0
▋By Routing
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class DemoController :
ControllerBase
{ }
Usage:
http://localhost:5000/api/v1/Demo/Get
http://localhost:5000/api/v2.0/Demo/Get
▋By HTTP Header
Update
the ConfigureServices
in Startup.cs
as following,
public void ConfigureServices(IServiceCollection services)
{
services.AddApiVersioning(opt =>
{
opt.ReportApiVersions = true;
opt.DefaultApiVersion
= new ApiVersion(1, 0);
opt.AssumeDefaultVersionWhenUnspecified = true;
opt.ApiVersionReader = new HeaderApiVersionReader("api-version");
opt.AssumeDefaultVersionWhenUnspecified = true;
opt.ApiVersionReader = new HeaderApiVersionReader("api-version");
});
}
We can specify more headers like
this,
opt.ApiVersionReader = new HeaderApiVersionReader("api-version","apver");
An HTTP
header example of a request:
GET <http://localhost:5000/api/Demo/Get>
HTTP/1.1
Host: localhost:5000
api-version: 2.0
▋By both header
or uri parameter
public void
ConfigureServices(IServiceCollection services)
{
services.AddApiVersioning(opt =>
{
opt.ReportApiVersions = true;
opt.DefaultApiVersion = new ApiVersion(1, 0);
opt.AssumeDefaultVersionWhenUnspecified
= true;
opt.ApiVersionReader = ApiVersionReader.Combine(
new QueryStringApiVersionReader("ver"),
new HeaderApiVersionReader("api-version")
);
});
}
▋Multiple version for non-modified APIs
[ApiVersion("1.0")]
[ApiVersion("2.0")]
[Route("api/[controller]")]
[ApiController]
public class DemoController :
ControllerBase
{
[HttpGet("Get")]
[MapToApiVersion("1.0")]
public ActionResult<IEnumerable<string>>
Get()
{
return new string[] { "Version", "v1.0" };
}
[HttpGet("Get")]
[MapToApiVersion("2.0")]
public ActionResult<IEnumerable<string>>
GetV2()
{
return new string[] { "Version", "v2.0" };
}
//This is a
non-modified action, available for versions 1.0/2.0`
[HttpPost("Post")]
public ActionResult<IEnumerable<string>>
Post()
{
return new string[] { "Version", "all" };
}
}
▋Demo : For
non-modified API
The
requests,
http://localhost:5000/api/Demo/Post
http://localhost:5000/api/Demo/Post?api-verson=1
http://localhost:5000/api/Demo/Post?api-version=2.0
Will get
the same response as following,
HTTP/1.1 200 OK
api-supported-versions: 1.0, 2.0
["Version","all"]
▋Deprecated version
[ApiVersion("1.0", Deprecated=true)]
[ApiVersion("2.0")]
[ApiVersion("3.0")]
[Route("api/[controller]")]
[ApiController]
public class DemoController :
ControllerBase
{
//...
}
▋Demo : Deprecated
information on Http response
HTTP/1.1 200 OK
api-supported-versions: 2.0, 3.0
api-deprecated-versions: 1.0
["Version","v2.0"]
▋Neutral API
For
those APIs that are not going to be
version controlled, use [ApiVersionNeutral]
to enable all versions available for them.
▋For all APIs in a ApiController
[ApiVersionNeutral]
[Route("api/[controller]")]
[ApiController]
public class
DemoNeutralController : ControllerBase
{ }
▋For a single API(Action)
[ApiVersionNeutral]
[HttpGet("Get")]
public ActionResult<IEnumerable<string>>
Get()
{
return new string[] { "Version",
HttpContext.GetRequestedApiVersion().ToString() };
}
▌Reference
沒有留言:
張貼留言