9

我有一个具有以下操作的 Web API 控制器:

    [HttpPut]
    public string Put(int id, JObject data)

    [HttpPut, ActionName("Lock")]
    public bool Lock(int id)

    [HttpPut, ActionName("Unlock")]
    public bool Unlock(int id)

并映射了以下路线:

        routes.MapHttpRoute(
            name: "Api",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        routes.MapHttpRoute(
            name: "ApiAction",
            routeTemplate: "api/{controller}/{action}/{id}"
        );

当我提出以下请求时,一切都按预期工作:

PUT /api/items/Lock/5
PUT /api/items/Unlock/5

但是当我尝试提出请求时:

PUT /api/items/5

我得到以下异常:

Multiple actions were found that match the request:
    Put(int id, JObject data)
    Lock(int id)
    Unlock(int id)

我尝试向默认路由添加一个空操作名称,但这没有帮助:

[HttpPut, ActionName("")]
public string Put(int id, JObject data)

有什么想法可以将默认的 RESTful 路由与自定义操作名称结合起来吗?

编辑:路由机制不会因控制器的选择而混淆。它对单个控制器上的操作选择感到困惑。我需要的是在未指定任何操作时匹配默认操作。希望能澄清事情。

4

3 回答 3

6

这是来自默认操作选择器的预期错误,即ApiControllerActionSelector. 您基本上具有三种对应于 HTTPPut动词的操作方法。还要记住,默认动作选择器考虑简单动作参数类型,它们都是原始 .NET 类型、众所周知的简单类型(System.StringSystem.DateTimeSystem.DecimalSystem.GuidSystem.DateTimeOffsetSystem.TimeSpan)和底层简单类型(例如:Nullable<System.Int32>)。

作为您的问题的解决方案,我将为以下控制器创建两个控制器:

public class FooController : ApiController { 

    public string Put(int id, JObject data)
}

public class FooRPCController : ApiController { 

    [HttpPut]
    public bool Lock(int id)

    [HttpPut]
    public bool Unlock(int id)
}

路线如下所示:

routes.MapHttpRoute(
    name: "ApiAction",
    routeTemplate: "api/Foo/{action}/{id}",
    defaults: new { controller = "FooRPC" }
);

routes.MapHttpRoute(
    name: "Api",
    routeTemplate: "api/Foo/{id}",
    defaults: new { id = RouteParameter.Optional, controller = "Foo" }
);

另一方面(与您的主题不完全相关),我有三篇关于动作选择的博客文章,尤其是复杂类型参数。我鼓励您查看它们,因为它们可能会给您更多的视角:

于 2012-10-29T20:09:33.847 回答
2

在Giscard Biamby的帮助下,我找到了这个答案,它为我指明了正确的方向。最终,为了解决这个特定问题,我这样做了:

routes.MapHttpRoute(
    name: "ApiPut", 
    routeTemplate: "api/{controller}/{id}",
    defaults: new { action = "Put" }, 
    constraints: new { httpMethod = new HttpMethodConstraint("Put") }
);

谢谢@GiscardBiamby

于 2012-11-29T18:39:21.970 回答
-3

首先,删除[HttpPut, ActionName("")]然后修改你的路线到这个

config.Routes.MapHttpRoute(
    name: "Api",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional },
    constraints: new { id = @"^[0-9]+$" }
    );  
于 2012-10-29T07:15:05.463 回答