我最初的问题是我正在寻找在Restful API中进行版本控制的最佳实践。没有多少人谈论这个问题,没有一个好的答案,或者我目前无法确切找到解决方案。

(1)首先,我想为每个版本http://domain.com/API/ {version}使用TagBranch。因此,如果发布了新的API,我将其Tag导出并发布到相应的URL中,但是似乎很难在一个Web应用程序中混合不同版本的源代码。

(2)然后我正在考虑使用这种方式,一个控制器用于一个版本:
(就像这个问题Versioning of REST API Built With ASP.NET MVC 3 - Best Practices

http://domain.com/API/1.0/{AnAction} => will go to APIV1Controller.{AnAction}

http://domain.com/API/2.0/{AnAction} => will go to APIV2Controller.{AnAction}

但它需要为每个版本写一条路由。

(3)第三种方式是从PayPal API中获得想法,即版本不在URL中,而在POST参数中。因此,URL固定为http://domain.com/API/,但用户必须指定Version参数以具有"1.0""2.0"

解决方案:(2)对我来说还可以,目前我使用这种方式,但是我想将(2)和(3)混合使用,所以我有一个APIController,该APIController仅具有一个Index操作来检查此Version参数并将请求传输到相应的控制器,然后执行APIV1Controller。{AnAction}或APIV2Controller。{AnAction}操作。

在Google搜索和Stackoverflowing有关如何转移,调用或调用另一个控制器和操作而不进行重定向之后。似乎没有好的答案和良好的实践。有人通过简单地创建控制器的新实例来回答.NET MVC Call method on different controller。突然我想到了reroute的想法!

问题:

是否可以在不重定向的情况下从另一个动作中reroute另一个控制器和另一个动作,该怎么做?

还是一个特定的问题,当用户向http://domain.com/API/{AnAction}请求Version="2.0"时,如何将rerouteAPIController.Index转换为APIV2Controller.{AnAction}

我没有使用IoC。

最佳答案

这可以通过路由约束来完成。首先实现IRouteConstraint

public class RequestParameterConstraint : IRouteConstraint
{
    public string ParameterName { get; private set; }
    public string ParameterValue { get; private set; }

    public RequestParameterConstraint(string parameter, string value)
    {
        ParameterName = parameter;
        ParameterValue = value;
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName,
        RouteValueDictionary values, RouteDirection routeDirection)
    {
        var value = httpContext.Request[ParameterName] ?? "";
        return value.Equals(ParameterValue);
    }
}


然后注册路线:

routes.MapRoute(
    "Version10",
    "API/{action}/{id}",
    new { controller = "APIV1", action = "Index", id = UrlParameter.Optional },
    new { header = new RequestParameterConstraint("Version", "1.0") }
    );

routes.MapRoute(
    "Version20",
    "API/{action}/{id}",
    new { controller = "APIV2", action = "Index", id = UrlParameter.Optional },
    new { header = new RequestParameterConstraint("Version", "2.0") }
    );


就这样。这将达到目的。

10-06 15:39