问题描述
在上一个asp.net web api
中,我实现了DefaultHttpControllerSelector
来指定我希望请求如何定位控制器.我经常使用名称不同但用于相同进程的不同控制器.唯一的区别是,一个版本的版本高于另一个版本.
In previous asp.net web api
, I implement DefaultHttpControllerSelector
to specify how I want the request to locate my controller. I often have different controllers with different names but intended for same processes. The only difference is that one is of higher version than the other.
例如,我可以有一个名为BookingV1Controller
的控制器,该控制器将用于处理服务的版本一.我还会有BookingV2Controller
,它旨在处理服务的第二版.然后,客户端应用程序将使用此URL http://myservice.com/api/v2/booking/someaction?id=12
向服务发出请求.为了处理该请求,我将提供DefaultHttpControllerSelector
的自定义实现,以根据请求的版本选择所需的控制器的适当版本.
For example, I could have a controller named BookingV1Controller
, which would be meant to handle the version one of the service. I would also have BookingV2Controller
, which was designed to handle the version two of the service. A client application would then make a request to the service with this url http://myservice.com/api/v2/booking/someaction?id=12
. To handle the request, I would provide a custom implementation of DefaultHttpControllerSelector
to select the appropriate version of the controller required based on the requested version.
但是,我似乎没有办法在ASP.NET Core
中执行此操作.我到处搜寻都无济于事.没有任何文档可以帮助您.
However, I seems not to have a way to do this in ASP.NET Core
. I have searched everywhere to no avail. No documentation that could help either.
如果有人可以在这里为我提供帮助,我将不胜感激.谢谢.
I would appreciate if anyone can be of help to me here. Thanks.
更新我还想知道如果在自定义标头中指定了版本,该怎么办.例如X-Version:v1
UPDATEI would also like to know what to do if the version is specified in a custom header. E.g X-Version:v1
更新2
要求是该服务的版本不应在URL中公开.如果不存在任何版本,该服务将返回有关如何添加版本的说明.如果请求的控制器不存在于请求的版本中,则系统会搜索较低的版本.如果在任何较低版本中找到它,它将使用该版本.这样做的原因是为了防止所有版本的控制器重复.但是,使用ASP.NET Core可能无法实现.
The requirement was that the version of the service should not be exposed in the URL. If no version is present, the service returns with instruction on how to add the version. If a requested controller is not present in the version requested, the system searches through the lower versions. If it finds it in any lower versions, it uses that. The reason for this is to prevent repetition of controllers on all versions. But with ASP.NET Core, this might not be possible.
推荐答案
我为此事花了几天的精力之后,才为此目的创建了一个程序包.它不需要属性.
I created a package for this purpose exactly after banging my head on this problem for a few days. It doesn't require attributes.
https://github.com/GoAheadTours/NamespaceVersioning
总而言之,您可以在启动文件中注册一个IApplicationModelConvention,该文件可以遍历控制器并根据命名空间注册路由.我创建了一个v1文件夹,并将控制器放入其中
In summary, you can register an IApplicationModelConvention in your startup file that can iterate through controllers and register routes based on the namespaces. I created a v1 folder, and put my controller inside
实现IApplicationModelConvention的类实现了带有ApplicationModel参数的Apply方法,该方法可以访问您应用中的Controller及其现有路由.如果我发现我的类中没有设置控制器的路由,那么我将从名称空间获取版本,并使用预定义的URL前缀为该版本生成路由.
The class that implements IApplicationModelConvention implements an Apply method with an ApplicationModel parameter that will have access to the Controllers in your app and their existing routes. If I see a controller does not have a route set up in my class I get the version from the namespace and use a pre-defined URL prefix to generate a route for that version.
public void Apply(ApplicationModel application) {
foreach (var controller in application.Controllers) {
var hasRouteAttribute = controller.Selectors.Any(x => x.AttributeRouteModel != null);
if (hasRouteAttribute) {
continue;
}
var nameSpace = controller.ControllerType.Namespace.Split('.');
var version = nameSpace.FirstOrDefault(x => Regex.IsMatch(x, @"[v][\d*]"));
if (string.IsNullOrEmpty(version)) {
continue;
}
controller.Selectors[0].AttributeRouteModel = new AttributeRouteModel() {
Template = string.Format(urlTemplate, apiPrefix, version, controller.ControllerName)
};
}
}
我在github上都有所有代码,在nuget上也有指向该包的链接
I have all the code up on github and a link to the package on nuget as well
这篇关于如何在ASP.NET Core Web Api中完成版本控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!