一个aspnet webapi控制器有两个get方法,并且发现了多个匹配请求的动作

时间:2013-05-10 22:15:14

标签: asp.net-web-api asp.net-web-api-routing

致电

http://mysite.com/Project/42

对于下面的路由和方法,我得到一个“找到了匹配请求的多个动作... Get(Int32)... Children(Int32)”

打电话

http://mysite.com/Project/42/Children

正确返回。

我的路由是:

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

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

我的方法:

public class ProjectController : ApiController {

    public IEnumerable<Project> Get(int id){
        ...
    }

    [HttpGet]
    public IEnumerable<Project> Children(int id) {
        ...
    }
}

我认为不指定该操作会导致Webapi默认为方法(GET)。现在看起来Webapi正在运行这些方法而忽略了它们的名称,只是寻找参数匹配。我真的不相信,认为我在其他地方有过错。

3 个答案:

答案 0 :(得分:1)

这是行动选择当前在Web API中的工作方式的已知行为/问题。在您的请求为“http://mysite.com/Project/42”的情况下,请求与“DefaultApi”路由匹配,并且在操作选择期间,操作选择器没有require变量“action”的值,因此它尝试从可通过GET方法获得的可用操作列表。它试图根据路由参数(如'id'在这里)和查询字符串参数找出se中的最佳动作。在您的场景中,操作选择器会看到2个获取操作,每个操作都接受id参数,因此在选择它们时会看到歧义。

此处提交的问题与您的方案类似: http://aspnetwebstack.codeplex.com/workitem/184

答案 1 :(得分:1)

一个简单的解决方案是只有一条路线:

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

然后装饰你的默认动作:

public class ProjectController : ApiController {

    [ActionName("DefaultAction")]
    public IEnumerable<Project> Get(){
        // api/project
        // Return all projects
    }

    [HttpGet]
    public IEnumerable<Project> Children(int id) {
        // api/project/1/children 
        // Return children of project with id == 1
    }
}

答案 2 :(得分:0)

在Web API 2中,您可以使用属性路由:

[RoutePrefix("Project")]
public class ProjectController : ApiController {

    [Route("{id:int}")]
    public IEnumerable<Project> Get(int id){
        ...
    }

    [HttpGet]
    [Route("{id:int}/Children")]
    public IEnumerable<Project> Children(int id) {
        ...
    }
}