ASP.NET核心属性路由

时间:2017-09-26 12:49:36

标签: c# asp.net-core asp.net-core-2.0 asp.net-core-routing

我正在将项目迁移到asp net core,但我无法配置这些路由,我使用属性来映射操作。

ASP.Net WebAPI2的代码

[Route("api/[controller]")]
public class SalesController : Controller
{
    // api/sales/1 -> ok
    [HttpGet]
    public HttpResponseMessage Get(int id)
    {
        // Logic
    }   

    // api/sales -> ok
    [HttpGet]
    public HttpResponseMessage Get([FromUri] PaginationHelper pagination)
    {
        // Logic
    }  

    // api/sales?me -> ok
    [ActionName("Get")]
    public HttpResponseMessage GetMe(bool? me)
    {
        // Logic
    }  
}

ASP.Net Core的代码

在文件 Startup.cs 中设置 app.UseMvc();

[Route("api/[controller]")]
public class SalesController : Controller
{
    // api/sales/1 -> ok
    [HttpGet("{id}")]
    public IActionResult Get(int id)
    {
        // Logic
    }   

    // api/sales -> don't work
    [HttpGet] // -> ???
    public IActionResult Get(PaginationHelper pagination)
    {
        // Logic
    }  

    // api/sales?me -> don't work
    [HttpGet] // -> ???
    public IActionResult GetMe(bool? me)
    {
        // Logic
    }  
}

3 个答案:

答案 0 :(得分:4)

新框架需要更明确地指示端点的意图。

[Route("api/[controller]")]
public class SalesController : Controller {

    [HttpGet("{id:int}")] // GET api/sales/1
    public IActionResult Get(int id) {
        // Logic
    }

    [HttpGet] // GET api/sales?page=1 assuming PaginationHelper has page property
    public IActionResult Get([FromQuery]PaginationHelper pagination) {
        // Logic
    } 

    [HttpGet] // GET api/sales?me=true
    public IActionResult GetMe(bool? me = false) {
        // Logic
    }  
}

参考Asp.Net Core: Model Binding

答案 1 :(得分:2)

也许我对这个讨论还为时过晚,但是这对于像我一样最终阅读此页面的其他人可能很有价值。 API端点的问题是您将其中两个端点配置为处理同一路由:GET /api/sales

如果您尝试访问该路由,则框架将无法区分Get(PaginationHelper)GetMe(bool?)。原因是它们都具有[HttpGet]属性,这意味着它们都能够处理您在类声明上方的[Route("api/[controller]")]属性中指定的路由。由于那些被声明为能够处理相同的路由,因此您的异常(Multiple actions matched)。

问题的解决方案取决于您要处理该歧义路线的操作。假设您希望GET /api/sales处理路由Get(PaginationHelper),则可以将GetMe(bool?)操作方法及其[HttpGet]属性更改为以下内容:

[HttpGet("me")] // GET api/sales/me
public IActionResult GetMe() {
    // Logic
}

答案 2 :(得分:0)

我们有一种非常干净的方法来使用令牌定义路由。

下面,我们仅在控制器级别的一个位置定义路由,这样做的好处是我们可以随时更改方法名称。

[Route("[controller]/[action]")]
public class DepartmentsController : Controller
{
    public string List()
    {
        return "List() of DepartmentsController";
    }

    public string Details()
    {
        return "Details() of DepartmentsController";
    }
}