为什么Web API Core 2无法区分这些?
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values?name=dave
[HttpGet]
public string Get(string name)
{
return $"name is {name}";
}
发生了什么 -
http://localhost:65528/api/values
和http://localhost:65528/api/values?name=dave
都会导致第一个Get()
方法执行。
这个确切的代码在Web Api 2中运行良好。
我know multiple解决此问题的方法,但我不知道为什么会发生这种情况。
有人可以解释为什么会发生变化吗?
答案 0 :(得分:1)
我认为您甚至无法在ASP.NET Core Mvc 2.0
中编译代码,因为您有2个操作映射到同一路由[HttGet] api/values
:
AmbiguousActionException: Multiple actions matched.
请记住,ASP.NET Web API
使用HTTP谓词作为请求的一部分来计算要调用的操作。虽然它使用常规路由(您将操作命名为Get,Post,Put和Delete等),但如果您没有指定路由属性,我强烈建议您始终使用路由属性来注释您的控制器和操作。
现在,作为开发人员,您可以自行设计路线。请记住,路由应该是Uri
,可以识别资源/资源。
使用名称作为标识符和路径
[Route("api/[controller]")]
public class CustomersController : Controller
{
// api/customers
[HttpGet]
public IActionResult Get()
{
...
}
/ api/customers/dave
[HttpGet("{name:alpha}")] // constraint as a string
public IActionResult GetByName(string name)
{
...
}
}
对资源集合
使用名称作为过滤器[Route("api/[controller]")]
public class CustomersController : Controller
{
// api/customers
// api/customers?name=dave
[HttpGet]
public IActionResult Get(string name)
{
...
}
}
api/customers/dave
仍将首先执行GetById
!
[Route("api/[controller]")]
public class CustomersController : Controller
{
[HttpGet]
public IActionResult Get()
{
...
}
[HttpGet("{name}")]
public IActionResult GetByName(string name)
{
...
}
[HttpGet("{id}")]
public IActionResult GetById(int id)
{
...
}
}
方法GetByName
和GetById
都是潜在候选者,但MVC首先选择GetById
方法,因为MVC通过案例比较方法/模板名称{name}
和{id}
- 敏感字符串比较,i
在n
之前。
当您想要约束时。
[Route("api/[controller]")]
public class CustomersController : Controller
{
[HttpGet]
public IActionResult Get()
{
...
}
// api/customers/dave
[HttpGet("{name:alpha}")]
public IActionResult GetByName(string name)
{
...
}
// api/customers/3
[HttpGet("{id:int}")]
public IActionResult GetById(int id)
{
...
}
}
您也可以指定订购!
[Route("api/[controller]")]
public class CustomersController : Controller
{
[HttpGet]
public IActionResult Get()
{
...
}
// api/customers/portland
[HttpGet("{city:alpha}", Order = 2)]
public IActionResult GetByCity(string city)
{
...
}
// api/customers/dave
[HttpGet("{name:alpha}", Order = 1)]
public IActionResult GetByName(string name)
{
...
}
// api/customers/3
[HttpGet("{id:int}")]
public IActionResult GetById(int id)
{
...
}
}
如果没有Order
,方法GetByCity
将优先于GetByName
,因为{city}
的字符c位于{name}
的字符n之前。但是,如果您指定订单,MVC将根据Order
选择操作。
感叹帖子太长了......
答案 1 :(得分:0)
因为在您的情况下,路由管道中的最佳匹配是默认的httpget属性(获取全部的属性)。该查询是一个常规字符串,因此如果您不从查询中询问您想要什么,那么最佳匹配仍然是获得所有匹配的。
[HttpGet]
public string Get([FromQuery]string name)
{
return $"name is {name}";
}
[FromQuery]指向查询字符串中的键“name”以获取值 您应该阅读Routing in asp.net core