Web Api Core 2 区分 GET

Bry*_*yan 2 routing asp.net-web-api asp.net-web-api-routing asp.net-core-2.0

为什么 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}";
    }
Run Code Online (Sandbox Code Playgroud)

这是发生了什么 -

二者http://localhost:65528/api/valueshttp://localhost:65528/api/values?name=dave引起所述第一Get()方法来执行。

这个确切的代码在 Web Api 2 中工作正常。

知道有 多种方法可以解决这个问题,但我不知道为什么会发生这种情况。

有人可以解释为什么这已经改变了吗?

Dav*_*ang 5

我认为您甚至无法编译代码,ASP.NET Core Mvc 2.0因为您有 2 个操作映射到同一路由[HttGet] api/values

AmbiguousActionException: Multiple actions matched.
Run Code Online (Sandbox Code Playgroud)

请记住,ASP.NET Web API使用 HTTP 动词作为请求的一部分来确定要调用的操作。虽然如果您没有指定路由属性,它使用传统路由(您将操作命名为 Get、Post、Put 和 Delete 等),但我强烈建议始终使用路由属性来注释您的控制器和操作。

Api 设计时间

现在由您作为开发人员来设计路线。请记住,路由应该是Uri可以识别资源/资源的。

  • 将名称与路线一起用作标识符

    AmbiguousActionException: Multiple actions matched.
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用名称作为过滤器,针对资源集合

    [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)
        {
            ...
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

更让你迷惑

api/customers/dave还是会GetById先执行!

[Route("api/[controller]")]
public class CustomersController : Controller
{
    // api/customers
    // api/customers?name=dave
    [HttpGet]
    public IActionResult Get(string name)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这两种方法GetByNameGetById都是潜在的候选者,但 MVCGetById首先选择方法,因为 MVC 比较方法/模板名称{name}{id}通过不区分大小写的字符串比较,并且in.

那是您想要放置约束的时候

[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)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

您也可以指定订购方式

[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)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

没有Order,该方法GetByCity将比GetByName因为字符 c{city}出现在 的字符 n 之前更受欢迎{name}。但是如果您指定顺序,MVC 将根据Order.

感叹帖子太长了....