两个HTTP Post方法在一个Web API控制器中具有不同的参数

时间:2013-02-21 12:06:25

标签: c# asp.net rest asp.net-web-api

我正在尝试在一个控制器中实现一个带有多个POST方法的Controller。我有以下内容:

public class PatientController : ApiController
{
    [HttpGet]
    public IEnumerable<Patient> All() { ... }

    [HttpGet]
    public Patient ByIndex(int index) { ... }

    [HttpPost]
    public HttpResponseMessage Add([FromBody]Patient patient) { ... }
}

我的路线上有这个:

GlobalConfiguration.Configuration.Routes.MapHttpRoute(
    "API_1",
    "{controller}/{index}",
    new { index = RouteParameter.Optional });

一切都按预期工作:)

现在,我想添加以下操作:

    [HttpPost, ActionName("save")]
    public void Save(int not_used = -1) { ... }

如果不向路由添加任何内容,我会向Fiddler收到以下错误:找到了与请求匹配的多个操作。

如果我将此添加到我的路由中(作为第二个或第一个,无关紧要):

GlobalConfiguration.Configuration.Routes.MapHttpRoute(
    "API_2",
    "{controller}/{action}/{not_used}",
    new { not_used = RouteParameter.Optional },
    new { action = "save|reset" }); // Action must be either save or reset

我向Fiddler犯了同样的错误。

这甚至可能吗?我可以在一个控制器中有多个具有不同(类型)参数的POST吗?

2 个答案:

答案 0 :(得分:1)

您的问题是,您有两种方法:SaveAdd,两者都匹配您的路线API_1。如果网址略有不同,您有另一条路径API_2可以匹配的事实并不重要:您有路线的两种匹配方法。

你有几个选择:

  1. 将save方法放在不同的控制器中,并且该控制器始终映射操作名称。
  2. 确保Save与默认路由不匹配。特别是,您在Save中包含了一个可选参数,这意味着可以省略。如果参数是非可选的,则它与路径不匹配。
  3. 更改您的体系结构以使用基于消息的格式;也就是说,而不是基于行为进行区分,只需传递一个类并根据它的设置进行区分(在web api中有点不寻常,但这就是ServiceStack所做的
  4. 将路由更改为始终包含操作名称。
  5. 如果不更好地理解你的具体情况,我真的不能说最好的东西;虽然我本人避免了让所有这些参数和同时路由处理多个操作的棘手问题 - 要么始终明确有关操作,要么在代码中解决任何可能的消息(即选项3或4)。面对可选参数的复杂路线只是一种痛苦。

答案 1 :(得分:0)

似乎我必须修改我的路由......

GlobalConfiguration.Configuration.Routes.MapHttpRoute(
    name: "API_2",
    routeTemplate: "{controller}/{action}/{not_used}",
    defaults: new { not_used = "-1" },
    constraints: new { action = "save|reset" });

GlobalConfiguration.Configuration.Routes.MapHttpRoute(
    name: "API_1",
    routeTemplate: "{controller}/{action}/{index}",
    defaults: new { action = "EMPTY", index = RouteParameter.Optional });

...并将ActionName属性添加到所有方法:

[HttpGet, ActionName("EMPTY")]
public IEnumerable<Patient> All()

[HttpGet, ActionName("EMPTY")]
public Patient ByIndex(int index)

[HttpPost, ActionName("EMPTY")]
public HttpResponseMessage Add([FromBody]Patient patient)

[HttpPost, ActionName("save")]
public void Save(int not_used = -1)

经过这些修改,我可以像这样调用保存:

localhost:6850/Patient/save