Web Api 核心 2 区分 GET
Web Api Core 2 distinguishing GETs
为什么 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 方法解决这个问题,但我不知道 为什么 它会发生。
有人可以解释为什么会这样吗?
我不认为你甚至可以在 ASP.NET Core Mvc 2.0
中编译你的代码,因为你有 2 个动作映射到相同的路径 [HttGet] api/values
:
AmbiguousActionException: Multiple actions matched.
请记住,ASP.NET Web API
使用 HTTP 谓词作为请求的一部分来确定调用哪个操作。尽管它使用常规路由(您将操作命名为 Get、Post、Put 和 Delete 等),但如果您没有指定路由属性,我强烈建议始终使用路由属性来注释您的控制器和操作。
Api 设计时间
现在轮到你作为开发者来设计路线了。请记住,路由应该是一个 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 比较 method/template 名称 {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
.
选择操作
唉post太长了....
因为在您的情况下,路由管道中的最佳匹配是默认的 httpget 属性(获取所有属性的属性)。查询是一个常规字符串,所以如果您不询问您想要从查询中得到什么,最佳匹配仍然是获得所有的那个。
[HttpGet]
public string Get([FromQuery]string name)
{
return $"name is {name}";
}
[FromQuery] 指向查询字符串中的键 "name" 以获取值。
你应该阅读 Routing in asp.net core
为什么 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 方法解决这个问题,但我不知道 为什么 它会发生。
有人可以解释为什么会这样吗?
我不认为你甚至可以在 ASP.NET Core Mvc 2.0
中编译你的代码,因为你有 2 个动作映射到相同的路径 [HttGet] api/values
:
AmbiguousActionException: Multiple actions matched.
请记住,ASP.NET Web API
使用 HTTP 谓词作为请求的一部分来确定调用哪个操作。尽管它使用常规路由(您将操作命名为 Get、Post、Put 和 Delete 等),但如果您没有指定路由属性,我强烈建议始终使用路由属性来注释您的控制器和操作。
Api 设计时间
现在轮到你作为开发者来设计路线了。请记住,路由应该是一个 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 比较 method/template 名称 {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
.
唉post太长了....
因为在您的情况下,路由管道中的最佳匹配是默认的 httpget 属性(获取所有属性的属性)。查询是一个常规字符串,所以如果您不询问您想要从查询中得到什么,最佳匹配仍然是获得所有的那个。
[HttpGet]
public string Get([FromQuery]string name)
{
return $"name is {name}";
}
[FromQuery] 指向查询字符串中的键 "name" 以获取值。
你应该阅读 Routing in asp.net core