【问题标题】:Optional parameter in .NET Core Web API route template.NET Core Web API 路由模板中的可选参数
【发布时间】:2021-08-17 01:57:18
【问题描述】:
[HttpGet("{pageNumber}{pageSize?}{filter?}{sortOrder?}", Name = "GetEntriesPaged")]
public ActionResult<List<Entry>> GetEntriesPaged(
    int pageNumber, int pageSize = 10, string filter = "", string sortOrder = "desc") {

运行时异常:

System.ArgumentException:可选参数必须在末尾 段。在细分 '{pageNumber}{pageSize?}{filter?}{sortOrder?}',可选参数 “pageSize”后跟“过滤器”。参数名称:路由模板

有什么意义?正如所要求的那样,我在段的末尾有一个可选参数....

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;
}

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

【问题讨论】:

    标签: c# asp.net-core asp.net-core-webapi


    【解决方案1】:

    不,你没有。 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());
    }
    

    【讨论】:

    • 我明白了,谢谢你的解释。但是我的意思是,异常消息令人困惑。我最后有一个可选参数。他们应该说一些关于唯一可选参数的内容,以减少混淆?! PS。您有什么解决问题的建议?
    • 在这里,使用查询字符串而不是路由 - 至少对于一些可选参数。您不能将它们全部包含在路由本身中,并且仍然保持它们是可选的。
    • 只需传递查询字符串中的值,即 ?pageSize=10
    • 我需要说“一旦你有 pageNumber => 使用这个功能”,也许只是 {pageNumber} 就足够了?但我已经[HttpGet("{id}", Name = "GetEntry")]
    • 要考虑的简单经验法则。使用路由参数唯一标识一个资源或资源集合。其他任何内容都是可选的,属于查询字符串。
    猜你喜欢
    • 2022-08-15
    • 2013-01-16
    • 1970-01-01
    • 2019-08-06
    • 2014-05-11
    • 1970-01-01
    • 2017-08-30
    • 1970-01-01
    • 2020-08-29
    相关资源
    最近更新 更多