CSharp - 在 Web API 控制器中,C# 多 HttpPost

  显示原文与译文双语对照的内容
70 2

我开始使用 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/TSPRoute或者http://localhost:52370/api/VTRouting/Route我得到了一个错误:

找到与请求匹配的多个操作

如果删除上述方法之一,则效果很好。

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中传递json为 MyRequestTemplate 。

时间:原作者:0个回答

125 5

你可以在一个控制器中有多个操作。

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

  • 首先使用 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}"
    );
原作者:
146 0

使用:

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

流行的信念相反,这种方法没有什么问题,并且它没有使用 Web API 。你仍然可以利用 Web API ( 。委托处理程序,内容协商,mediatypeformatters等)的所有出色特性- 你只需放弃RESTful方法。

原作者:
56 5

更好的解决方案是使用 Route 可以以使用注释指定方法上的路由:

[RoutePrefix("api/VTRouting")]
public class VTRoutingController : ApiController
{
 [HttpPost]
 [Route("Route")]
 public MyResult Route(MyRequestTemplate routingRequestTemplate)
 {
 return null;
 }
 [HttpPost]
 [Route("TSPRoute")]
 public MyResult TSPRoute(MyRequestTemplate routingRequestTemplate)
 {
 return null;
 }
}
原作者:
50 1

Web API 端点( 控制器) 是接受 get/post/put/delete 谓词的单个资源。它不是普通的MVC控制器花费了

必须至少有一个 HttpPost方法接受发送的参数。如果你用材质装饰的话,函数 NAME 不重要。但我从未尝试过。

Edit: 这不工作。在解析中,似乎是按参数的数量进行的,而不是试图将绑定绑定到类型。

你可以重载函数以接受不同的参数。我非常确定,如果你按照你的方式声明它,但是使用不同的( 不兼容) 参数对方法。如果参数是相同的,那么你就没有幸运了,模型绑定将不知道你的意思。

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

这个零件

当你创建新的模板时,它们给出的默认模板使得这一点非常明显,我应该遵守这个约定:

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使用,没有大的原因使用标准控制器/动作 Pattern 。唯一真正的差别是你的方法签名不是那么漂亮,你必须在返回它们之前在 Json( returnValue) 中包装东西。

编辑:

使用简单类型时使用标准模板( 已经编辑为包含) 时,重载工作正常。我已经用其他方法测试过了,带有不同签名的2个自定义对象。永远不能让它工作。

在这种情况下,这是为我工作的,看看。仅用于测试的异常。

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' } )
原作者:
...