【发布时间】:2019-05-28 22:11:48
【问题描述】:
我创建了一个带有版本控制的 Web API 应用程序。我将使用Microsoft.AspNet.WebApi.Versioning 包来做到这一点。
Webapi配置:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.AddApiVersioning(o => {
o.AssumeDefaultVersionWhenUnspecified = true;
});
// Web API routes
config.MapHttpAttributeRoutes();
}
}
这里我的假设是如果我没有通过版本,默认情况下它会选择版本 1。
控制器代码:
[ApiVersion("1.0")]
[RoutePrefix("api/users")]
public class UserV1Controller : BaseController
{
public UserV1Controller()
{
}
[Route("all", Name = "UsersCollection")]
public async Task<IHttpActionResult> GetAll()
{
var items = await UnitOfWork.Users.GetPaged(x => x.OrderBy(y => y.Id), 1, 20);
//Add mapping to DTO
return Ok(items);
}
}
如果我使用http://localhost:10280/api/users/all?api-version=1.0 URL 进行测试,它可以正常工作。我将在现有项目中实现此功能。
为了向后兼容,我尝试了http://localhost:10280/api/users/all URL。
它给了我以 500 作为状态码的以下错误。
{ "Message": "发生错误。",
"ExceptionMessage": "索引不能小于 0 或等于或大于集合中的项目数。\r\n
参数 名称:索引\r\n实际值为 0。",
"ExceptionType": "System.ArgumentOutOfRangeException",
"StackTrace": "在
System.Web.Http.WebHost.Routing.HostedHttpRouteCollection.get_Item(Int32 索引)\r\n 在 Microsoft.Web.Http.Dispatcher.ApiVersionControllerSelector.GetControllerName(HttpRequestMessage 请求)\r\n 在 Microsoft.Web.Http.Dispatcher.ControllerSelectionContext.c__DisplayClass6_0.<.ctor>b__0()\r\n 在 System.Lazy1.CreateValue()\r\n at System.Lazy1.LazyInitValue()\r\n 在 System.Lazy`1.get_Value()\r\n
在 Microsoft.Web.Http.Dispatcher.ConventionRouteControllerSelector.SelectController(ControllerSelectionContext 上下文)\r\n 在 Microsoft.Web.Http.Dispatcher.ApiVersionControllerSelector.SelectController(HttpRequestMessage 请求)\r\n 在 System.Web.Http.Dispatcher.HttpControllerDispatcher.d__15.MoveNext()" }
更新 1:
经过讨论和一些帮助,我可以确认这个默认版本适用于传统路由。
使用属性路由时重现该问题。请检查我更新的代码。
- 我在 WebAPIConfig 文件中没有任何默认 API 路由。
- 我在控制器中更新了路由前缀和路由
现在问题重现了。
您还可以通过结合常规和属性来重现该问题。
更新 2:
现在我注意到问题在于配置。如果我直接在 Owin 启动类中添加路由配置,它工作正常。
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
var configuration = new System.Web.Http.HttpConfiguration();
var httpServer = new System.Web.Http.HttpServer(configuration);
// reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
configuration.AddApiVersioning(options =>
{
options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true;
});
configuration.MapHttpAttributeRoutes();
app.UseWebApi(httpServer);
}
}
它会创建新的 HttpConfiguration,而不是使用我们现有的 WebAPIConfig 类。所以我不知道它可能会影响任何其他功能
因此,如果我将 Owin 配置为使用 webaPI 而不是 Global.asax 中的 GlobalConfiguration.Configure(WebApiConfig.Register),它可以正常工作。
【问题讨论】:
-
这是 mvc 的路由配置。我们需要您的 webapi 的路由配置。如果不更改,这很可能位于 WebApiConfig.cs 中
-
好的。所以只有我糊涂了。实际上,我删除了默认路由线,因为我只为属性路由配置。我现在更新了。对不起,如果我让你感到困惑。
-
不。没关系。您的路线配置似乎没问题。我现在可以安全地重现您的错误。现在让我们为它找到一个解决方案
-
好的,谢谢。我尝试了所有指定的方式。如果没有得到任何东西似乎可以通过扩展 ControllerSelector
-
是否有使用版本 2 的控制器,具有相同的路由前缀?例如
[RoutePrefix("api/users")]?因为这导致您在我的本地项目中出错。如果我删除第二个控制器或其路由前缀,错误就会消失。这是很自然的,因为 2 个不同的控制器不能有 2 个相同的路由。
标签: c# asp.net-web-api asp.net-web-api2 api-versioning