0

我为我的 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'是动作并且使用方法和动作,匹配正确的方法吗?我想我错过了一些东西。

4

1 回答 1

0

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

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

在此之后,路由模板“DefaultControllerWithAction”应该很好地整理出“/api/users/byemail”

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

edit2:
刚刚对此进行了测试,Kip Streithorst 的解决方案适合您的情况。

第 1 步:硬编码默认值,而不是指定该操作是可选的。
第 2 步:使用硬编码的默认操作名称装饰您的“基于动词的控制器”

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

    config.Routes.MapHttpRoute(
        名称:“DefaultControllerWithAction”,
        routeTemplate: "api/{controller}/{action}",
        默认值:新 { action = "DefaultAction }
        );
    config.Routes.MapHttpRoute(
        名称:“DefaultGetWithId”,
        routeTemplate: "api/{controller}/{id}",
        默认值:新 { action = "Get" },
        约束:新 { httpMethod = 新 HttpMethodConstraint(HttpMethod.Get) }
        );
    config.Routes.MapHttpRoute(
        name: "DefaultControllerWithIdAndAction",
        routeTemplate: "api/{controller}/{id}/{action}",
        默认值:新 { action = "DefaultAction" }
        );

    [动作名称(“默认动作”)]
    公共 UserDto 获取(字符串 id){}

    [HttpGet]
    公共 UserDto ByEmail(字符串电子邮件)

    [HttpGet]
    公共布尔 IsEmailUnique(字符串电子邮件)
于 2013-03-29T14:26:32.970 回答