DateTime 的通用端点还是三个不同的端点?

Posted

技术标签:

【中文标题】DateTime 的通用端点还是三个不同的端点?【英文标题】:Generic endpoint for DateTime or three different endpoints? 【发布时间】:2020-12-07 03:05:26 【问题描述】:

我有一个问题,因为我以前遇到过这种情况,我想知道最佳做法。

假设您想要这三个端点。

host:port/api/movies/published/2012 从 '2012' 返回所有按发布日期(M13,M1)排序的 host:port/api/movies/published/2012/8 从 '2012-08' 返回全部按发布日期(M1)排序 host:port/api/movies/published/2012/8/15 返回所有来自 '2012-08-15' 的按发布日期(M1)排序

你会做一个像这样的通用端点,或者在这些情况下什么是最佳实践?你会怎么解决呢?

[HttpGet("published/year:int/month:int?/day:int?/")]
public void GetMoviesSortedByPublishedDateAsync(int year, int month = 0, int day = 0)


    if (month == 0)
    
        var date = new DateTime(year, 1, 1);
        await _cosmosDbService.GetMoviesByYear(date.Year);
    
    else if(day == 0)
    
        var date = new DateTime(year, month, 1);
        await _cosmosDbService.GetMoviesByYearAndMonth(date.Year, date.Month);
    
    else
    
        var date = new DateTime(year, month, day);
        await _cosmosDbService.GetMoviesByPublishedDate(date);
    

【问题讨论】:

老实说,您的代码看起来是一种足够体面的方法。它不工作吗? 为什么你需要这三个?第一个应该付出一切。所以你的解决方案是给出重复和三次。您从第一个查询中获得所有信息。然后,您会在 8 月获得所有内容的副本。然后在 8 月 15 日重复三次。 我的意思是,它应该可以工作,但是有没有更好更有效的方法来解决它? 【参考方案1】:

您所拥有的可能会起作用,但它确实有一些可能的缺点,包括在 URL 路径中构建参数最终会创建无限数量的可能路径。如果您想分析或过滤您的流量日志或以其他方式进行额外的请求处理,解析这些路径组合可能会带来一些麻烦。

将日期作为查询字符串中的参数似乎是一种更好的做法,更多idiomatic to REST URL 也是如此。它可以是ISO 8601 format 中的日期前缀,它自然是可排序的。然后,您的查询可以利用 Cosmos DB 中的本机 STARTSWITH 来有效地过滤和排序 publishedDate 属性。

它可能看起来像这样:

[HttpGet("published")]
public void GetMoviesSortedByPublishedDateAsync(string published)

    if(!string.IsNullOrEmpty(published) // Validate better than this :)
    
        // Queries container where published date STARTSWITH specified value
        await _cosmosDbService.GetMoviesByPublishPrefix(published);
    

可能的值可以是任何有效的日期前缀,可选的 2 位数日/月:

2020 => GET https://app.com/movies?published=2020
2020-03 => GET https://app.com/movies?published=2020-03
2020-03-13 => GET https://app.com/movies?published=2020-03-01

【讨论】:

嗨,我最终使用了这个解决方案,但它只有在我使用 published=2020-03 的情况下才有效,但如果用户发送它时像 published=2020-3 一样不带零。然后 STARTSWITH 不会返回对象。 是的,如果需要,您需要确保输入是左填充的:***.com/questions/3459610/pad-with-leading-zeros【参考方案2】:

为什么不这样简化:

[HttpGet("published/year:int/month:int?/day:int?/")]
public void GetMoviesSortedByPublishedDateAsync(int year, int month = 1, int day = 1)

    var date = new DateTime(year, month, day);
    await _cosmosDbService.GetMoviesByPublishedDate(date);

您的搜索可以是具体的,如果他们不提供月份并不重要,因为无论如何您都会从给定年份的开始进行搜索(当天相同)

您最终得到的代码更少,而且也更简单。

【讨论】:

如果他们提供日期和年份呢? @mjwills 公平的问题,但是,你如何在 api 上调用它? http://.../year/(null?)/2 :shrug: 这可能吗? 我认为这完全取决于GetMoviesByPublishedDate 的实现方式。从这个问题来看,我认为这种方法只会返回该特定日期的数据。因此,使用此解决方案,我希望仅提供 2012 年的请求仅返回 2102-01-01 的数据,而不是 2012 年的所有数据 @devNull 是的 ..english 很有趣 ...return all from 可以从给定日期或从该日期开始建议 ?【参考方案3】:

你会做一个像这样的通用端点吗?或者在这些情况下什么是最佳实践?

我认为应该根据 API 的可能使用方式做出决定。此 API 的使用者很可能会有类似的过滤选项(按年、按月、按日期)——在这种情况下,使用单个端点会更好。

最佳实践而言,这里是an interesting take,支持您的方法 - 请查看允许过滤、排序和分页部分。

【讨论】:

以上是关于DateTime 的通用端点还是三个不同的端点?的主要内容,如果未能解决你的问题,请参考以下文章

在 web.config 中添加第三个端点显示错误

同一浏览器页面中两个端点之间的WebRTC?

TCP 端点如何知道另一个端点是关闭了连接的两半还是只关闭了一个?

在 Kestrel 上为 ASP.NET Core 上的两个不同端点发布两个不同的端点

Sql Azure Dac 导入/导出服务是 WCF 或 REST 还是其他?

公共和私有端点是不是应该有单独的 API? [关闭]