5

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

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 吗?

4

2 回答 2

1

您的问题是您有两种方法:Saveand Add,并且都匹配您的 route API_1。如果 url 稍有不同,您有另一个API_2可能匹配的路由这一事实并不重要:您有两个匹配路由的方法。

你有几个选择:

  1. 将 save 方法放在不同的控制器中,并为该控制器始终映射操作名称。
  2. 确保Save与默认路由不匹配。特别是,您在 Save 中包含了一个可选参数,这意味着可以省略。如果参数是非可选的,它将与路由不匹配。
  3. 更改您的架构以使用基于消息的格式;即,不是基于动作进行区分,而是简单地传递一个类并根据它的设置方式进行区分(在 web api 中有点不寻常,但这ServiceStack就是
  4. 更改您的路由以始终包含操作名称。

如果不更好地了解您的确切情况,我真的不能说什么是最好的;虽然我个人会避免让所有这些参数和同时路由处理多个动作的棘手问题——要么总是明确说明动作,要么在代码中处理任何可能的消息(即选项 3 或 4)。面对可选参数的复杂路线简直是一种痛苦。

于 2013-02-21T12:55:09.740 回答
1

看来我必须修改我的路由...

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
于 2013-02-21T14:05:41.433 回答