Asp.net web api Web Api核心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

为什么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 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,非常有用