【发布时间】:2019-11-06 09:36:27
【问题描述】:
经过多次尝试和阅读文章后,我决定将我的问题放在这里。我想要的是以下内容:我正在研究应用程序的 api 版本。 .NET Core(Microsoft.AspNetCore.Mvc.Versioning 包)支持的版本格式是 Major.Minor,这是我想在我从事的项目中使用的版本。我想要的是一个备用版本,以防客户端未指定次要版本。
我正在使用 .NET core 2.2,并使用标题中指定的 api-version。相应的 API 版本控制配置如下所示:
services.AddApiVersioning(options => {
options.ReportApiVersions = true;
options.ApiVersionReader = new HeaderApiVersionReader("api-version");
options.ErrorResponses = new ApiVersioningErrorResponseProvider();
});
每个版本我都有以下两个控制器:(为了这个 SO 问题,控制器被简化了):
[ApiVersion("1.0")]
[Route("api/[controller]")]
public class ValueControllerV10 : Controller
{
[HttpGet(Name = "collect")]
public String Collect()
{
return "Version 1.0";
}
}
[ApiVersion("1.1")]
[Route("api/[controller]")]
public class ValueControllerV11 : Controller
{
[HttpGet(Name = "collect")]
public String Collect()
{
return "Version 1.1";
}
}
如果客户端指定api-version=1.0,则使用 ValueControllerV10。当然,如果客户端指定api-version=1.1,那么正如预期的那样使用ValueControllerV11。
现在我的问题来了。如果客户端指定api-version=1(所以只有主版本没有次版本),那么使用ValueControllerV10。这是因为ApiVersion.Parse("1") 等于ApiVersion.Parse("1.0"),如果我没记错的话。但在这种情况下,我想要调用给定主要版本的最新版本,在我的示例中为 1.1。
我的尝试:
首先:在ValueControllerV11指定[ApiVersion("1")]
[ApiVersion("1")]
[ApiVersion("1.1")]
[Route("api/[controller]")]
public class ValueControllerV11 : Controller
{
[HttpGet(Name = "collect")]
public String Collect()
{
return "Version 1.1";
}
}
它不起作用,它导致
AmbiguousMatchException: The request matched multiple endpoints
为了解决这个问题,我想出了第二种方法:
第二:使用自定义IActionConstraint。为此,我关注了这些文章:
- https://stevenknox.net/aspnet-core-mvc-action-priority-using-actionconstraints/
- https://www.strathweb.com/2017/06/using-iactionconstraints-in-asp-net-core-mvc/
然后我创建了以下类:
[AttributeUsage(AttributeTargets.Method)]
public class HttpRequestPriority : Attribute, IActionConstraint
{
public int Order
{
get
{
return 0;
}
}
public bool Accept(ActionConstraintContext context)
{
var requestedApiVersion = context.RouteContext.HttpContext.GetRequestedApiVersion();
if (requestedApiVersion.MajorVersion.Equals(1) && !requestedApiVersion.MinorVersion.HasValue)
{
return true;
}
return false;
}
}
并在ValueControllerV11使用:
[ApiVersion("1")]
[ApiVersion("1.1")]
[Route("api/[controller]")]
public class ValueControllerV11 : Controller
{
[HttpGet(Name = "collect")]
[HttpRequestPriority]
public String Collect()
{
return "Version 1.1";
}
}
好吧,它解决了AmbiguousMatchException,但是覆盖了Microsoft.AspNetCore.Mvc.Versioning包的默认行为,所以如果客户端使用api-version 1.1,那么她会得到一个404 Not Found,根据@987654343的实现这是可以理解的@
第三:在Startup.cs中使用MapSpaFallbackRoute,有条件地:
app.MapWhen(x => x.GetRequestedApiVersion().Equals("1") && x.GetRequestedApiVersion().MinorVersion == null, builder =>
{
builder.UseMvc(routes =>
{
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new {controller = nameof(ValueControllerV11), action = "Collect"});
});
});
app.UseMvc();
它也不起作用,没有任何影响。 MapSpaFallbackRoute这个名字也给我一种感觉,不是我需要用的……
所以我的问题是:在api-version 中未指定次要版本的情况下,如何引入后备“使用最新”行为?提前致谢!
【问题讨论】:
标签: asp.net-mvc asp.net-web-api .net-core api-versioning