You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Framework 4.8 Web API版本控制配置失效求助

.NET Framework 4.8 Web API版本控制故障排查

问题背景

开发.NET Framework 4.8 Web API项目时,尝试为REST API端点启用版本控制,但所有端点均无法正常响应,请求返回资源未找到或版本未指定的错误。

控制器代码

namespace Testproject1.Controllers
{
    using Testproject.Controllers.Models;
    using Asp.Versioning;
    using System.Web.Http;

    [ApiVersion(1.0)]
    [Route("api/v{version:apiVersion}/[controller]")]
    public class AgreementsController: ApiController
    {
        [Route("{accountId}")]
        public IHttpActionResult Get(string accountId) =>
            Ok(new Agreement(GetType().FullName, accountId, "1"));
    }
}

namespace Testproject1.Controllers
{
    using Testproject.Controllers.Models;
    using Asp.Versioning;
    using System.Web.Http;

    [ApiVersion(2.0)]
    [Route("api/v{version:apiVersion}/[controller]")]
    public class AgreementsControllerv2 : ApiController
    {
        [Route("{accountId}")]
        public IHttpActionResult Get(string accountId) =>
            Ok(new Agreement(GetType().FullName, accountId, "2"));
    }
}

namespace Testproject1.Controllers.V1
{
    using Testproject.Controllers.Models;
    using Asp.Versioning;
    using System.Web.Http;

    [ApiVersion(2.0)]
    [Route("api/v{version:apiVersion}/[controller]")]
    public class OrdersController : ApiController
    {
        // GET ~/v1/orders/{accountId}
        [Route("{accountId}")]
        public IHttpActionResult Get(string accountId) =>
            Ok(new Order(GetType().FullName, accountId, "1"));
    }
}

Startup配置代码

var configuration = new HttpConfiguration();
var httpServer = new HttpServer(configuration);
configuration.MapHttpAttributeRoutes();

configuration.AddApiVersioning(
            options =>
            {
                options.ReportApiVersions = true;
                options.DefaultApiVersion = new ApiVersion(1, 0);
                options.AssumeDefaultVersionWhenUnspecified = true;
                options.ApiVersionReader = new UrlSegmentApiVersionReader();
            });

configuration.Routes.MapHttpRoute(
            name: "VersionedApi",
            routeTemplate: "api/v{version:apiVersion}/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional, version = RouteParameter.Optional });

builder.UseWebApi(httpServer);

错误响应

  • 版本1请求:http://localhost:9999/api/v1.0/agreements/1
{
    "消息": "未找到与请求URI 'http://localhost:9999/api/v2.0/agreements/1' 匹配的HTTP资源。",
    "消息详情": "在控制器 'Agreements' 上未找到与请求匹配的操作。"
}
  • 版本2请求:http://localhost:9999/api/v2.0/agreements/1
{
    "消息": "未找到与请求URI 'http://localhost:9999/api/v1.0/agreements/1' 匹配的HTTP资源。",
    "消息详情": "在控制器 'Agreements' 上未找到与请求匹配的操作。"
}
  • Orders请求:http://localhost:9999/api/v2.0/orders/1
{
    "代码": "ApiVersionUnspecified",
    "跟踪ID": "776cf174-79ab-4386-a856-2f385f5f51ca",
    "类型": "https://docs.api-versioning.org/problems#unspecified",
    "标题": "未指定API版本",
    "状态码": 400,
    "详情": "需要API版本,但未指定。"
}

问题分析与修复方案

1. Startup配置顺序错误

API版本控制的配置必须在属性路由映射之前执行,否则版本读取器无法正确解析属性路由中的{version:apiVersion}参数。

修复:调整Startup代码顺序,先配置API版本控制,再映射属性路由:

var configuration = new HttpConfiguration();
var httpServer = new HttpServer(configuration);

// 先配置API版本控制
configuration.AddApiVersioning(
            options =>
            {
                options.ReportApiVersions = true;
                options.DefaultApiVersion = new ApiVersion(1, 0);
                options.AssumeDefaultVersionWhenUnspecified = true;
                options.ApiVersionReader = new UrlSegmentApiVersionReader();
            });

// 再映射属性路由
configuration.MapHttpAttributeRoutes();

configuration.Routes.MapHttpRoute(
            name: "VersionedApi",
            routeTemplate: "api/v{version:apiVersion}/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional, version = RouteParameter.Optional });

builder.UseWebApi(httpServer);

2. AgreementsControllerv2控制器路由解析错误

控制器类名为AgreementsControllerv2,路由中的[controller]会自动解析为AgreementsControllerv2,导致请求api/v2.0/agreements/1无法匹配到该控制器。

修复:给AgreementsControllerv2添加[ControllerName]属性,指定控制器的路由名称为Agreements:

[ApiVersion(2.0)]
[ControllerName("Agreements")] // 添加此属性
[Route("api/v{version:apiVersion}/[controller]")]
public class AgreementsControllerv2 : ApiController
{
    [Route("{accountId}")]
    public IHttpActionResult Get(string accountId) =>
        Ok(new Agreement(GetType().FullName, accountId, "2"));
}

3. OrdersController版本与路由匹配问题

OrdersController标记了[ApiVersion(2.0)],但之前的Startup顺序错误导致版本读取器无法识别URL中的版本参数,修复Startup顺序后即可解决"未指定API版本"的错误。

验证修复

调整后重新运行项目,测试以下请求:

  • http://localhost:9999/api/v1.0/agreements/1:应返回AgreementsController的响应
  • http://localhost:9999/api/v2.0/agreements/1:应返回AgreementsControllerv2的响应
  • http://localhost:9999/api/v2.0/orders/1:应返回OrdersController的响应

内容的提问来源于stack exchange,提问作者user1258028

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 06:42:33