.NET Core Web API路由模板中的可选参数

Ser*_*rge 5 asp.net-core asp.net-core-webapi asp.net-core-webapi-2.1

[HttpGet("{pageNumber}{pageSize?}{filter?}{sortOrder?}", Name = "GetEntriesPaged")]
public ActionResult<List<Entry>> GetEntriesPaged(
    int pageNumber, int pageSize = 10, string filter = "", string sortOrder = "desc") {
Run Code Online (Sandbox Code Playgroud)

运行时异常:

System.ArgumentException:可选参数必须位于该段的末尾。在“ {pageNumber} {pageSize?} {filter?} {sortOrder?}”段中,可选参数“ pageSize”后跟“ filter”。参数名称:routeTemplate

有什么意义?根据要求,我在该段的末尾有一个可选参数。

PS。更完整的代码:

[HttpGet]
public ActionResult<List<Entry>> GetAll() {
    var result = _db.Entries.OrderByDescending(x => x.Date).ToList();
    return result;
}

[HttpGet("{pageNumber}{pageSize?}{filter?}{sortOrder?}", Name = "GetEntriesPaged")]
public ActionResult<List<Entry>> GetEntriesPaged(int pageNumber = 1, int pageSize = 10, string filter = "", string sortOrder = "desc") {
    int take = pageSize;
    int skip = ((pageNumber - 1) * pageSize);
    IQueryable<Entry> result;

    if (sortOrder == "asc") {
        result = _db.Entries.OrderBy(x => x.Date);
    }
    else {
        result = _db.Entries.OrderByDescending(x => x.Date);
    }

    return result.Skip(skip).Take(take).Where(x => x.Origin.Contains(filter)).ToList();
}

[HttpGet("{id}", Name = "GetEntry")]
public ActionResult<Entry> GetById(long id) {
    var item = _db.Entries.Find(id);
    if (item == null) {
        return NotFound();
    }
    return item;
}
Run Code Online (Sandbox Code Playgroud)

我需要/entriesGetAll()方法使用,但/esntries?pageNumber=3GetEntriesPaged(...)一个

Chr*_*att 5

不,你不会。sortOrder是年底,但pageSizefilter没有。简而言之,您不能有多个这样的可选参数。它创建了太多的路由组合,这将导致无法确定如何路由请求或要填充的特定路由参数。例如,如果你在填写什么pageSizesortOrder,但不filter?ASP.NET Core应该如何知道您提供的sortOrder内容实际上并不意味着filter

FWIW,您还需要在这些路线参数之间使用斜线。否则,就无法知道下一个结点在哪里,下一个结点在哪里开始。例如,是否有这样的路线,比如说/111说一个页面的大小为11,页面11的大小为1或页面111,并且没有设置大小?但这仍然无法帮助您将它们全部设置为可选。

如果URL中需要多个可选内容,则最好仅使用查询字符串来提供它们。

更新

您不需要,也应该实际上不应该对页面进行多个操作。通用功能过多,差异太小。典型公式为:

public async Task<IActionResult> GetAll(int? page = null, int pageSize = 10)
{
    var query = _context.Foos;
    if (page.HasValue)
    {
        query = query.Skip((page.Value - 1) * pageSize).Take(pageSize);
    }

    return Ok(await query.ToListAsync());
}
Run Code Online (Sandbox Code Playgroud)

  • 要考虑的简单经验法则。使用路由参数来“唯一地标识”资源或资源集合。其他任何内容都是可选的,并且属于查询字符串。 (2认同)