Asp.net web api Web Api核心2
为什么WebAPI核心2不能区分这些Asp.net web api Web Api核心2,asp.net-web-api,routing,asp.net-web-api-routing,asp.net-core-2.0,Asp.net Web Api,Routing,Asp.net Web Api Routing,Asp.net Core 2.0,为什么WebAPI核心2不能区分这些 [HttpGet] public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } // GET api/values?name=dave [HttpGet] public string Get(string name) { return $"name
[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}";
}
[HttpGet]
公共IEnumerable Get()
{
返回新字符串[]{“value1”,“value2”};
}
//获取api/值?name=dave
[HttpGet]
公共字符串获取(字符串名称)
{
返回$“name为{name}”;
}
下面是发生的事情-
两者都http://localhost:65528/api/values
和http://localhost:65528/api/values?name=dave
执行第一个Get()
方法
这段代码在WebAPI2中运行良好
我有很多办法来解决这个问题,但我不知道为什么会这样
有人能解释一下为什么会发生变化吗?我认为你甚至不能在
ASP.NET Core Mvc 2.0
中编译你的代码,因为你有两个动作映射到了相同的路径[HttGet]api/值
:
AmbiguousActionException: Multiple actions matched.
请记住,ASP.NET Web API
将HTTP动词用作请求的一部分,以确定要调用的操作。虽然它使用常规路由(您可以命名操作Get、Post、Put和Delete等),但如果您没有指定路由属性,我强烈建议始终使用路由属性来注释控制器和操作
Api设计时间
现在,作为一名开发人员,由您来设计路线。请记住,路由应该是可以识别资源的Uri
- 将名称与路由一起用作标识符
[路由(“api/[控制器]”)] 公共类CustomerController:控制器 { //api/客户 [HttpGet] public IActionResult Get() { ... } //api/客户/dave [HttpGet(“{name:alpha}”)]//约束为字符串 公共IActionResult GetByName(字符串名称) { ... } }
- 对资源集合使用名称作为筛选器
[路由(“api/[控制器]”)] 公共类CustomerController:控制器 { //api/客户 //api/客户?名称=dave [HttpGet] 公共IActionResult Get(字符串名称) { ... } }
api/customers/dave
仍将首先执行GetById
[路由(“api/[控制器]”)]
公共类CustomerController:控制器
{
[HttpGet]
public IActionResult Get()
{
...
}
[HttpGet(“{name}”)]
公共IActionResult GetByName(字符串名称)
{
...
}
[HttpGet(“{id}”)]
公共IActionResult GetById(int id)
{
...
}
}
两种方法GetByName
和GetById
都是潜在的候选方法,但是MVC首先选择GetById
方法,因为MVC通过不区分大小写的字符串比较来比较方法/模板名{name}
和{id}
,并且i
在n
之前
此时您需要设置约束
[路由(“api/[控制器]”)]
公共类CustomerController:控制器
{
[HttpGet]
public IActionResult Get()
{
...
}
//api/客户/dave
[HttpGet(“{name:alpha}”)]
公共IActionResult GetByName(字符串名称)
{
...
}
//api/客户/3
[HttpGet(“{id:int}”)]
公共IActionResult GetById(int id)
{
...
}
}
您还可以指定顺序
[路由(“api/[控制器]”)]
公共类CustomerController:控制器
{
[HttpGet]
public IActionResult Get()
{
...
}
//api/客户/波特兰
[HttpGet(“{city:alpha}”,顺序=2)]
公共IActionResult GetByCity(字符串城市)
{
...
}
//api/客户/dave
[HttpGet(“{name:alpha}”,顺序=1)]
公共IActionResult GetByName(字符串名称)
{
...
}
//api/客户/3
[HttpGet(“{id:int}”)]
公共IActionResult GetById(int id)
{
...
}
}
没有顺序
,方法GetByCity
将比GetByName
更有利,因为{city}
的字符c在{name}
的字符n之前。但是如果您指定了顺序,MVC将根据顺序选择操作
叹息帖子太长了……因为在您的例子中,路由管道中的最佳匹配是默认的httpget属性(获取全部的属性)。查询是一个常规字符串,因此,如果您不询问您希望从查询中得到什么,那么最好的匹配仍然是获得全部信息的匹配
[HttpGet]
public string Get([FromQuery]string name)
{
return $"name is {name}";
}
[FromQuery]指向查询字符串中的键“name”以获取值。
您应该阅读我不认为查询字符串用于路由。您可以对此进行扩展吗?作为记录,属性路由的第22条规则之一是,路由顺序是一个重要的设计因素,默认情况下,.NET属性顺序未定义。这意味着您必须始终注意,如果您有类似的路线,则需要对其进行排序(或约束)。基于约定的路由通常需要更少的配置,更具扩展性和功能,并且指定顺序与按正确顺序声明它们一样简单。谢谢David,非常有用