【问题标题】:Two HTTP Post method with different parameters in one Web API controller一个 Web API 控制器中具有不同参数的两个 HTTP Post 方法
【发布时间】:2013-02-21 12:06:25
【问题描述】:

我正在尝试在一个控制器中实现一个具有多个 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 吗?

【问题讨论】:

  • 你打电话的网址是什么?另外,你真的没有在 api URL 中使用普通的 /api 前缀吗?
  • 是的,没有 api - 该项目根本不包含 MVC。当使用以下 POST localhost:6850/Patient/ 对 im 进行定位时

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


【解决方案1】:

您的问题是您有两种方法:SaveAdd,并且都匹配您的路线API_1。如果 url 稍有不同,您还有另一条路线 API_2 可能匹配的事实并不重要:您有两种匹配方法用于 this 路线。

你有几个选择:

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

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

【讨论】:

  • 嗨,我的目标是实现路由,以便客户端可以在不传递保存参数的情况下调用控制器->“localhost:6850/Patient/save”。“保存控制器”是一个选项,但我想将功能保留在一个类中,即使它不适合 REST 世界。关于路由,有没有办法指定它以便我当前的接口可以工作?
【解决方案2】:

看来我得修改我的路由了……

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-30
    相关资源
    最近更新 更多