“发现多个动作”错误

时间:2013-03-29 13:53:41

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

我的web api服务设置了以下默认路由...

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

config.Routes.MapHttpRoute(
    name: "DefaultPost",
    routeTemplate: "api/{controller}",
    defaults: new { action = "Post" },
    constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) }
    );

config.Routes.MapHttpRoute(
    name: "DefaultGetWithId",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { action = "Get" },
    constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) }
    );

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

config.Routes.MapHttpRoute(
    name: "DefaultDeleteWithId",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { action = "Delete" },
    constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Delete) }
    );

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

我在'UsersController'下有以下服务:

public UserDto Get(string id){}

[HttpGet]
public UserDto ByEmail(string email)

[HttpGet]
public bool IsEmailUnique(string email)

问题是当我尝试点击这三种服务中的任何一种时,我收到了“发现多个操作”错误。请求应从所有路由中选择最后一条路由并执行请求。

如果我要执行'/api/users/byemail?email=blah@blah.com',不应该知道'ByEmail'是动作并使用方法&动作,匹配正确的方法?我想我错过了什么。

1 个答案:

答案 0 :(得分:0)

似乎您已将BeEmail和IsEmailUnique方法映射到GET操作,这导致找到多个操作。

由于您已经为命名操作设置了路径模板(DefaultControllerWithAction),因此您可以删除[HttpGet]属性。

在此之后,routetemplate“DefaultControllerWithAction”应该排除'/ api / users / byemail'就好了

修改的 似乎在同一个ApiController中混合传统和基于动词的路由存在问题。 这是记录here on codeplex,有一篇博客文章声称解决了这个问题(尚未测试): http://blog.appliedis.com/2013/03/25/web-api-mixing-traditional-verb-based-routing/

EDIT2:
刚刚对此进行了测试,Kip Streithorst的解决方案可以解决您的问题。

Step 1:hardcode a default value instead of specifying that action is optional.
Step 2:decorate your "verb-based controllers with the hardcoded default action name

对于你的获取请求,这将是:

    config.Routes.MapHttpRoute(
        name: "DefaultControllerWithAction",
        routeTemplate: "api/{controller}/{action}",
        defaults: new { action = "DefaultAction }
        );
    config.Routes.MapHttpRoute(
        name: "DefaultGetWithId",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { action = "Get" },
        constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) }
        );
    config.Routes.MapHttpRoute(
        name: "DefaultControllerWithIdAndAction",
        routeTemplate: "api/{controller}/{id}/{action}",
        defaults: new { action = "DefaultAction" }
        );

    [ActionName("DefaultAction")]
    public UserDto Get(string id){}

    [HttpGet]
    public UserDto ByEmail(string email)

    [HttpGet]
    public bool IsEmailUnique(string email)