经过多次尝试和阅读文章,我决定将我的问题放在这里。我想要的是以下内容:我正在研究应用程序的 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。
我的尝试:
第一:指定[ApiVersion("1")]
在ValueControllerV11
[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
package 的默认行为,所以如果客户端使用api-version 1.1
,那么她会得到一个 404 Not Found ,根据实现是可以理解的HttpRequestPriority
第三:有条件地使用MapSpaFallbackRoute
in Startup.cs
:
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
?提前致谢!