Web API控制器中的多个HttpPost方法

我开始使用MVC4 Web API项目,我有多个HttpPost方法的控制器。 控制器如下所示:

调节器

 public class VTRoutingController : ApiController { [HttpPost] public MyResult Route(MyRequestTemplate routingRequestTemplate) { return null; } [HttpPost] public MyResult TSPRoute(MyRequestTemplate routingRequestTemplate) { return null; } } 

这里MyRequestTemplate表示负责处理来自请求的Json的模板类。

错误:

当我使用Fiddler为http://localhost:52370/api/VTRouting/TSPRoutehttp://localhost:52370/api/VTRouting/Route ,出现错误:

发现多个与请求匹配的操作

如果我删除上述方法之一,它工作正常。

Global.asax中

我已经尝试修改global.asax的默认路由表,但我仍然收到错误,我想我在global.asax中定义路由有问题。 这是我在做的global.asax。

 public static void RegisterRoutes(RouteCollection routes) { routes.MapHttpRoute( name: "MyTSPRoute", routeTemplate: "api/VTRouting/TSPRoute", defaults: new { } ); routes.MapHttpRoute( name: "MyRoute", routeTemplate: "api/VTRouting/Route", defaults: new {action="Route" } ); } 

我使用POST在Fiddler中发送请求,并在RequestBody中为MyRequestTemplate传递json。

您可以在单个控制器中执行多个操作。

为此你必须做以下两件事。

  • 首先用ActionName属性来装饰动作

      [ActionName("route")]` public class VTRoutingController : ApiController { [ActionName("route")] public MyResult PostRoute(MyRequestTemplate routingRequestTemplate) { return null; } [ActionName("tspRoute")] public MyResult PostTSPRoute(MyRequestTemplate routingRequestTemplate) { return null; } } 
  • 其次在WebApiConfig文件中定义以下路由。

     // Controller Only // To handle routes like `/api/VTRouting` config.Routes.MapHttpRoute( name: "ControllerOnly", routeTemplate: "api/{controller}" ); // Controller with ID // To handle routes like `/api/VTRouting/1` config.Routes.MapHttpRoute( name: "ControllerAndId", routeTemplate: "api/{controller}/{id}", defaults: null, constraints: new { id = @"^\d+$" } // Only integers ); // Controllers with Actions // To handle routes like `/api/VTRouting/route` config.Routes.MapHttpRoute( name: "ControllerAndAction", routeTemplate: "api/{controller}/{action}" ); 

使用:

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

它不再是一个REST风格的方法,但是现在可以通过名称来调用你的动作(而不是让Web API根据动词自动为你确定一个动作):

 [POST] /api/VTRouting/TSPRoute [POST] /api/VTRouting/Route 

与stream行的观点相反,这种方法没有任何问题,也没有滥用Web API。 您仍然可以利用Web API的所有优秀特性(委托处理程序,内容协商,中介格式化等) – 您只是抛弃了RESTful方法。

对您的问题更好的解决scheme是使用“路由”,让您通过注释指定方法上的路线

 [Route("Route")] [HttpPost] public MyResult Route(MyRequestTemplate routingRequestTemplate) { return null; } [Route("TSPRoute")] [HttpPost] public MyResult TSPRoute(MyRequestTemplate routingRequestTemplate) { return null; } 

Web api端点(控制器)是接受get / post / put / delete动词的单个资源。 这不是一个正常的MVC控制器。

必须在/api/VTRouting中只能有一个 HttpPost方法接受你发送的参数。 函数名称无关紧要 ,只要你用[http]东西来装饰。 但我从来没有尝试过。

编辑:这不起作用。 在解决这个问题的时候,似乎只是通过参数的数量,而不是试图模型绑定到types。

您可以重载函数来接受不同的参数。 我敢肯定,如果您按照自己的方式进行声明,则可以使用不同的(不兼容的)参数。 如果参数相同,则模型绑定不会知道您的意思。

 [HttpPost] public MyResult Route(MyRequestTemplate routingRequestTemplate) {...} [HttpPost] public MyResult TSPRoute(MyOtherTemplate routingRequestTemplate) {...} 

这部分工作

他们创build一个新的默认模板使得这个非常明确,我想说你应该坚持这个约定:

 public class ValuesController : ApiController { // GET is overloaded here. one method takes a param, the other not. // GET api/values public IEnumerable<string> Get() { .. return new string[] ... } // GET api/values/5 public string Get(int id) { return "hi there"; } // POST api/values (OVERLOADED) public void Post(string value) { ... } public void Post(string value, string anotherValue) { ... } // PUT api/values/5 public void Put(int id, string value) {} // DELETE api/values/5 public void Delete(int id) {} } 

如果你想使一个类做很多事情,对于Ajax使用,没有大的理由不使用标准的控制器/动作模式。 唯一真正的区别是你的方法签名不是很漂亮,你必须在Json( returnValue)之前把东西包装在Json( returnValue)

编辑:

使用简单types时使用标准模板(编辑包含)时,重载工作得很好。 我已经去了另一种方式,用2个不同的签名自定义对象。 永远不可能得到它的工作。

  • 绑定复杂的对象看起来不“深”,所以这是一个不行
  • 你可以通过在查询string上传递一个额外的参数来解决这个问题
  • 比我可以提供的选项更好的写法

在这种情况下,这对我有用,看看它在哪里得到你。 仅用于testing的例外。

 public class NerdyController : ApiController { public void Post(string type, Obj o) { throw new Exception("Type=" + type + ", o.Name=" + o.Name ); } } public class Obj { public string Name { get; set; } public string Age { get; set; } } 

并像这样调用控制台:

 $.post("/api/Nerdy?type=white", { 'Name':'Slim', 'Age':'21' } ) 

可以在同一个Web API控制器中添加多个Get和Post方法。 这里的默认路由是导致问题。 Web API检查从顶部到底部的匹配路由,因此您的默认路由匹配所有请求。 根据默认路由,一个控制器中只能有一个获取和发布方法。 将以下代码置于顶部或注释掉/删除默认路线

  config.Routes.MapHttpRoute("API Default", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional }); 

在路由前缀[RoutePrefix(“api / Profiles”)]在控制器级别,并在行动方法[路由(“LikeProfile”)]的路线。 不需要在global.asax文件中改变任何东西

 namespace KhandalVipra.Controllers { [RoutePrefix("api/Profiles")] public class ProfilesController : ApiController { // POST: api/Profiles/LikeProfile [Authorize] [HttpPost] [Route("LikeProfile")] [ResponseType(typeof(List<Like>))] public async Task<IHttpActionResult> LikeProfile() { } } } 
 public class Journal : ApiController { public MyResult Get(journal id) { return null; } } public class Journal : ApiController { public MyResult Get(journal id, publication id) { return null; } } 

我不确定重载get / post方法是否违反了restfull api的概念,但是它是可行的。 如果有人可以在这个问题上启发。 如果我有一个uri,怎么办?

 uri:/api/journal/journalid uri:/api/journal/journalid/publicationid 

所以你可能会看到我的日记sorting的aggregateroot,虽然我可以定义另一个控制器的出版物,并通过身份证号码在我的url发布然而,这给了更多的意义。 因为没有期刊本身,我的出版就不存在。

我刚刚添加了“action = action_name”到这个url,这样路由引擎就知道我想要的是什么动作。 我也添加了ActionName属性的行动,但我不知道这是必要的。

我想这个问题已经答复了。 我也在寻找一个webApi控制器,它具有相同的签名但名称不同。 我试图将计算器实现为WebApi。 计算器有4个方法具有相同的签名但名称不同。

 public class CalculatorController : ApiController { [HttpGet] [ActionName("Add")] public string Add(int num1 = 1, int num2 = 1, int timeDelay = 1) { Thread.Sleep(1000 * timeDelay); return string.Format("Add = {0}", num1 + num2); } [HttpGet] [ActionName("Sub")] public string Sub(int num1 = 1, int num2 = 1, int timeDelay = 1) { Thread.Sleep(1000 * timeDelay); return string.Format("Subtract result = {0}", num1 - num2); } [HttpGet] [ActionName("Mul")] public string Mul(int num1 = 1, int num2 = 1, int timeDelay = 1) { Thread.Sleep(1000 * timeDelay); return string.Format("Multiplication result = {0}", num1 * num2); } [HttpGet] [ActionName("Div")] public string Div(int num1 = 1, int num2 = 1, int timeDelay = 1) { Thread.Sleep(1000 * timeDelay); return string.Format("Division result = {0}", num1 / num2); } } 

和你已经拥有的WebApiConfig文件

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

只需在IIS上设置身份validation/授权,即可完成!

希望这可以帮助!