我开始使用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中定义路由时遇到问题。这是我在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。
答案 0 :(得分:138)
您可以在一个控制器中执行多项操作。
为此你必须做以下两件事。
首先使用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}"
);
答案 1 :(得分:31)
对您的问题更好的解决方案是使用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;
}
}
答案 2 :(得分:26)
使用:
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
它不再是RESTful方法,但您现在可以通过名称调用您的操作(而不是让Web API根据动词自动为您确定一个),如下所示:
[POST] /api/VTRouting/TSPRoute
[POST] /api/VTRouting/Route
与流行的看法相反,这种方法没有任何问题,也没有滥用Web API。您仍然可以利用Web API的所有强大功能(委派处理程序,内容协商,mediatype格式等) - 您只是放弃了RESTful方法。
答案 3 :(得分:11)
web api端点(控制器)是一个接受get / post / put / delete动词的单一资源。它是不正常的MVC控制器。
必要时,/api/VTRouting
只能有一个 HttpPost方法接受您要发送的参数。只要您使用[http]内容进行装饰,函数名称无关紧要。不过,我从未尝试过。
编辑:这不起作用。在解析时,它似乎是通过参数的数量,而不是尝试模型绑定到类型。
您可以重载函数以接受不同的参数。如果你按照你的方式声明它,我很确定你会好的,但是对方法使用了不同的(不兼容的)参数。如果参数相同,那么你运气不好,因为模型绑定不会知道你的意思。
[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使用,没有什么大的理由不使用标准的控制器/动作模式。唯一真正的区别是你的方法签名不是很漂亮,你必须在返回之前将内容包装在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' } )
答案 4 :(得分:6)
可以在同一个Web API Controller中添加多个Get和Post方法。默认路由是导致问题。 Web API检查从上到下的匹配路由,从而检查所有请求的默认路由匹配。根据默认路由,在一个控制器中只能使用一个Get和Post方法。将以下代码置于顶部或注释/删除默认路由
config.Routes.MapHttpRoute("API Default",
"api/{controller}/{action}/{id}",
new { id = RouteParameter.Optional });
答案 5 :(得分:1)
将Route Prefix [RoutePrefix(“api / Profiles”)]置于控制器级别,并在行动方法[Route(“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()
{
}
}
}
答案 6 :(得分:1)
您可以使用这种方法:
public class VTRoutingController : ApiController
{
[HttpPost("Route")]
public MyResult Route(MyRequestTemplate routingRequestTemplate)
{
return null;
}
[HttpPost("TSPRoute")]
public MyResult TSPRoute(MyRequestTemplate routingRequestTemplate)
{
return null;
}
}
答案 7 :(得分:0)
我刚刚在网址中添加了“action = action_name”,这样路由引擎知道我想要什么操作。我还将ActionName属性添加到了操作中,但我不确定是否需要它。
答案 8 :(得分:0)
我认为这个问题已经得到了回答。我也在寻找一些webApi控制器,它具有相同的标记但名称不同的mehtods。我试图将计算器实现为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上设置身份验证/授权即可完成!
希望这有帮助!
答案 9 :(得分:-1)
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
因为你可能会看到我的期刊类似的聚合,但我可以单独定义另一个控制器进行发布,并在我的网址中传递发布的id号但是这更有意义。因为没有期刊本身,我的出版物就不存在了。
答案 10 :(得分:-1)
我在该主题上看到的最好,最简单的解释- http://www.binaryintellect.net/articles/9db02aa1-c193-421e-94d0-926e440ed297.aspx
我只使用Route,而不需要RoutePrefix。
例如,在控制器中
[HttpPost]
[Route("[action]")]
public IActionResult PostCustomer
([FromBody]CustomerOrder obj)
{
}
和
[HttpPost]
[Route("[action]")]
public IActionResult PostCustomerAndOrder
([FromBody]CustomerOrder obj)
{
}
然后,函数名称在jquery中以-
options.url = "/api/customer/PostCustomer";
或
options.url = "/api/customer/PostCustomerAndOrder";