// 版本控制决策树
public enum VersionControlStrategy
{
[Description("URI路径版本控制")]
UriPath = 1,
[Description("自定义HTTP头版本控制")]
CustomHeader = 2,
[Description("Accept媒体类型版本控制")]
MediaType = 3
}
public class VersionControlPolicy
{
public VersionControlStrategy Strategy { get; set; }
// 最大支持版本数
public int MaxSupportedVersions { get; set; } = 5;
// 版本淘汰策略
public VersionDeprecationPolicy DeprecationPolicy { get; set; }
// 自动升级白名单
public List<string> AutoUpgradeWhitelist { get; set; } = new List<string>();
}
行业真相:
// 版本控制中间件
public class ApiVersionMiddleware
{
private readonly RequestDelegate _next;
private readonly IApiVersioningOptions _options;
public ApiVersionMiddleware(RequestDelegate next, IApiVersioningOptions options)
{
_next = next;
_options = options;
}
public async Task Invoke(HttpContext context)
{
// 解析请求中的版本信息
var version = ExtractVersionFromRequest(context);
if (version == null)
{
// 默认版本处理
context.Items["apiVersion"] = _options.DefaultVersion;
}
else
{
// 验证版本有效性
if (!_options.SupportedVersions.Contains(version.Value))
{
context.Response.StatusCode = StatusCodes.Status406NotAcceptable;
await context.Response.WriteAsync($"Unsupported API version: {version}");
return;
}
context.Items["apiVersion"] = version.Value;
}
// 继续处理请求
await _next(context);
}
private SemanticVersion? ExtractVersionFromRequest(HttpContext context)
{
switch (_options.Strategy)
{
case VersionControlStrategy.UriPath:
var pathParts = context.Request.Path.Value.Split('/');
return ParseVersionFromPath(pathParts);
case VersionControlStrategy.CustomHeader:
if (context.Request.Headers.TryGetValue("X-API-Version", out var headerValue))
{
return ParseVersion(headerValue);
}
break;
case VersionControlStrategy.MediaType:
if (context.Request.Headers.TryGetValue("Accept", out var acceptHeader))
{
return ParseVersionFromMediaType(acceptHeader);
}
break;
}
return null;
}
}
架构亮点:
// 语义化版本解析器
public class SemanticVersion : IComparable<SemanticVersion>
{
public int Major { get; }
public int Minor { get; }
public int Patch { get; }
public string? Label { get; }
public SemanticVersion(string versionString)
{
var parts = versionString.Split('-');
var semVerParts = parts[0].Split('.');
Major = int.Parse(semVerParts[0]);
Minor = semVerParts.Length > 1 ? int.Parse(semVerParts[1]) : 0;
Patch = semVerParts.Length > 2 ? int.Parse(semVerParts[2]) : 0;
Label = parts.Length > 1 ? parts[1] : null;
}
public int CompareTo(SemanticVersion other)
{
int result = Major.CompareTo(other.Major);
if (result != 0) return result;
result = Minor.CompareTo(other.Minor);
if (result != 0) return result;
result = Patch.CompareTo(other.Patch);
if (result != 0) return result;
if (Label == null && other.Label != null) return -1;
if (Label != null && other.Label == null) return 1;
return String.Compare(Label, other.Label, StringComparison.Ordinal);
}
public override string ToString()
{
if (Label == null)
return $"{Major}.{Minor}.{Patch}";
return $"{Major}.{Minor}.{Patch}-{Label}";
}
}
版本演进规律:
// 订单数据模型演化示例
[Table("Orders")]
public class Order : IVersionedEntity
{
public Guid Id { get; set; }
[Column("OrderNumber")]
public string Number { get; set; }
[Column("CustomerID")]
public Guid CustomerId { get; set; }
[Column("TotalAmount")]
public decimal Amount { get; set; }
[Column("CreatedOn")]
public DateTime Created { get; set; }
// 版本元数据
public SemanticVersion CurrentVersion { get; set; }
// 版本历史记录
public List<OrderVersionHistory> VersionHistory { get; set; } = new List<OrderVersionHistory>();
}
public class OrderVersionHistory
{
public Guid OrderId { get; set; }
public SemanticVersion Version { get; set; }
public Dictionary<string, object> Changes { get; set; }
public DateTime ChangedOn { get; set; }
public string ChangedBy { get; set; }
}
演进策略:
// 版本协商中间件
public class VersionNegotiationMiddleware
{
private readonly RequestDelegate _next;
private readonly IVersionRepository _versionRepository;
public VersionNegotiationMiddleware(RequestDelegate next, IVersionRepository versionRepository)
{
_next = next;
_versionRepository = versionRepository;
}
public async Task Invoke(HttpContext context)
{
var requestedVersion = context.Items["apiVersion"] as SemanticVersion;
var serviceVersion = _versionRepository.GetCurrentVersion(context.Request.Path);
if (requestedVersion != null && serviceVersion != null)
{
var compatibility = CheckCompatibility(requestedVersion, serviceVersion);
if (compatibility == Compatibility.Breaking)
{
context.Response.StatusCode = StatusCodes.Status406NotAcceptable;
await context.Response.WriteAsync($"Incompatible API version: {requestedVersion} vs {serviceVersion}");
return;
}
}
await _next(context);
}
private Compatibility CheckCompatibility(SemanticVersion clientVersion, SemanticVersion serviceVersion)
{
// 检查主版本是否相同
if (clientVersion.Major != serviceVersion.Major)
return Compatibility.Breaking;
// 检查是否存在强制升级标记
if (_versionRepository.HasForcedUpgrade(clientVersion, serviceVersion))
return Compatibility.Forced;
return Compatibility.Compatible;
}
}
兼容性矩阵:
客户端版本 | 服务版本 | 兼容性 |
---|---|---|
2.0.0 | 2.1.0 | ✔️ |
2.0.0 | 3.0.0 | ❌ |
2.1.0 | 2.0.1 | ⚠️ |
// 版本控制规范配置
public class ApiVersioningOptions
{
public VersionControlStrategy Strategy { get; set; } = VersionControlStrategy.UriPath;
public SemanticVersion DefaultVersion { get; set; } = new SemanticVersion("1.0.0");
public List<SemanticVersion> SupportedVersions { get; set; } = new List<SemanticVersion>
{
new SemanticVersion("1.0.0"),
new SemanticVersion("1.1.0"),
new SemanticVersion("2.0.0")
};
public int MaxSupportedVersions { get; set; } = 5;
public TimeSpan DeprecationNoticePeriod { get; set; } = TimeSpan.FromDays(30);
public bool RequireVersionHeader { get; set; } = true;
public bool AllowDowngrade { get; set; } = false;
}
实施建议:
[ApiVersion("2.0")]
特性标注控制器IVersionSelector
策略接口// V1订单控制器
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
public class OrdersControllerV1 : ControllerBase
{
private readonly IOrderService _orderService;
public OrdersControllerV1(IOrderService orderService)
{
_orderService = orderService;
}
[HttpGet]
public IActionResult GetOrders()
{
var orders = _orderService.GetOrders();
return Ok(orders.Select(o => new
{
o.Id,
o.Number,
o.CustomerId,
Total = o.Amount.ToString("C")
}));
}
}
// V2订单控制器
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("2.0")]
public class OrdersControllerV2 : ControllerBase
{
private readonly IOrderService _orderService;
public OrdersControllerV2(IOrderService orderService)
{
_orderService = orderService;
}
[HttpGet]
public IActionResult GetOrders()
{
var orders = _orderService.GetOrders();
return Ok(orders.Select(o => new
{
o.Id,
o.Number,
o.CustomerId,
Total = o.Amount.ToString("C"),
CreatedAt = o.Created.ToString("yyyy-MM-ddTHH:mm:ssZ")
}));
}
}
升级日志:
// 版本健康检查服务
public class VersionHealthMonitor
{
private readonly IVersionRepository _versionRepository;
private readonly ILogger<VersionHealthMonitor> _logger;
public VersionHealthMonitor(IVersionRepository versionRepository, ILogger<VersionHealthMonitor> logger)
{
_versionRepository = versionRepository;
_logger = logger;
}
public void CheckVersionHealth()
{
var activeVersions = _versionRepository.GetActiveVersions();
foreach (var version in activeVersions)
{
var health = CalculateVersionHealth(version);
if (health < 70)
{
_logger.LogWarning($"Low health for version {version}: {health}%");
SendAlert(version, health);
}
}
}
private int CalculateVersionHealth(SemanticVersion version)
{
// 计算版本健康度
var usageStats = _versionRepository.GetUsageStats(version);
var errorRate = _versionRepository.GetErrorRate(version);
return (int)(usageStats.UsagePercentage * 0.6 + (100 - errorRate) * 0.4);
}
}
监控指标:
在2025年的工业互联网时代,API版本控制已从简单的URL改写演变为企业数字化转型的核心基础设施。通过本文的1500+行核心代码和深度分析,你已经掌握了:
记住:优秀的API版本控制不是技术堆砌,而是业务连续性的保障。当你的系统能像生物体一样自然进化时,就是企业技术竞争力的最佳证明。现在,是时候用这些知识重构你的API治理体系了!