Web Api 结合使用控制器和不使用控制器的路由

Web Api routes with controller and without controller in conjunction

我有两个控制器。

具有经典 REST 功能的一个。

public class ValuesController : ApiController
{
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
    public string Get(int id)
    {
        return "value";
    }
}

还有一个带有带有 HttpAttributes 的自定义函数名称

     public class Values2Controller : ApiController
{
    [HttpGet]
    public IEnumerable<string> GetAll()
    {
        return new string[] { "value2_1", "value2_2" };
    }
    [HttpGet]
    public string GetById(int id)
    {
        return "value " + id;
    }
}

我的路线配置如下

   config.Routes.MapHttpRoute(
            name: "DefaultApi2",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

使用此设置

http://localhost:xxxxx/api/Values2/1 没有得到解决

如果我将 DefaultApi 放在 DefaultApi2 之前然后尝试访问

http://localhost:xxxxx/api/Values2/GetAll

我得到"The parameters dictionary contains a null entry for parameter 'id' "

问题是您的路由定义不明确。例如,对于这个 URL:

http://localhost:xxxxx/api/Values2/1

路由系统可以认为“1”段是 DefaultApi2 路由中的操作,而 Id 是空的,因为您已经这样定义了它。

因此,要打破歧义,您需要使用路由约束。这允许您将规则添加到路线的不同部分,以免它们不匹配。请记住,路由是按照它们注册的顺序进行评估的。

因此,例如,如果您先注册 DefaultApi,然后注册 DefaultApi2,并添加一个约束,要求第一个路由的 Id 为数字,则两个路由将完美运行。

您还可以在控制器名称上添加约束,或者为每种控制器使用不同的前缀,例如 api/api2/。案例是可以区分路由的。

Google "Web API route contraints",你会得到这样的信息:

RouteCollectionExtensions.MapHttpRoute Method (RouteCollection, String, String, Object, Object) 的 MSDN 文档毫无用处。