PUT 查询字符串的正确格式是怎样的?

How is the correct format for a PUT querystring?

我需要构建一个 PUT 方法,该方法将接收保险单号和相关期间的星级日期。此方法将更新开始相关期间,因此由于有更新,该方法被定义为 PUT 动词。

我的方法的正确格式是什么?我对两种可能的正确格式感到困惑:

http://<url>:<port>/api/valuation/<policy number>/<start date>

http://<url>:<port>/api/valuation/<policy number>

并从正文中接收日期?

在这两种情况下,如何声明路由(我使用的是 .net framework 4.5)

对于选项 #1

[Route("UpdatePeriod/{numPolicy}/{startDate}")]
public IHttpActionResult UpdatePeriod(string numPolicy, string startDate)

对于选项 #2

[Route("UpdatePeriod/{numPolicy}")]
public IHttpActionResult UpdatePeriod(string numPolicy, [fromBody] string startDate)

有人可以给我提示吗?我对此有点迷茫。

提前致谢。

这可能归结为偏好,但我要补充的是,它实际上是关于以一种合乎逻辑的方式组织 URL,这种方式使用名词和动作是有意义的。因此,它实际上是在遵循最佳实践和约定的同时最直观、最合理地表示数据的工作方式。

让我们看看你的例子。

http://<url>:<port>/api/valuation/<policy number>/<start date>

当我查看它时,在我看来,这代表存在多个具有相同保单编号的保单的数据,并且您想将其过滤为具有提供的开始日期的一个。我不确定您的数据看起来如何,或者是否应该始终有一份有效的保单编号,但这对我来说没有多大意义。

http://<url>:<port>/api/valuation/<policy number>

这向我表明,根据保单编号,只有一份保单。这似乎是更有可能的情况,所以我将从这个作为情况 1 开始。

场景 1

如果您知道您将根据一份给定保单编号的有效保单行事,那么将开始日期放在URL。您需要在通过 body 获得的 POST 数据中使用它,因为您将根据该保险单行事。在这种情况下,#2 是您的赌注,you'll want to make "valuation" plural.

您的 URL 看起来像这样:

# returns all insurance policies`
GET "http://<url>:<port>/api/valuations"

# returns one insurance policy with given policy number
GET "http://<url>:<port>/api/valuations/<policy number>"

# acts upon the insurance policy with that number, very broad
PUT "http://<url>:<port>/api/valuations/<policy number>"

# acts upon the insurance policy with number but in a more specific way with a dedicated method 
# start date would be in your post that you would then bind to a view model
PUT "http://<url>:<port>/api/valuations/<policy number>/startdate"

场景 2

如果您知道在给定保单编号的情况下您将获取不止一份保单,并且想在开始日期之前对其进行过滤,那么将它放在 URL 中是有意义的。 URL 看起来像这样:

PUT http://<url>:<port>/api/valuations/<policy number>/startdate/<start date>

为什么?因为您正在根据具有相同保单编号但不同开始日期的保单列表中的一份保单行事。

所以你的 URL 看起来像这样:

# returns all valuations insurance policies`
GET "http://<url>:<port>/api/valuations"

# returns list of insurance policies with the same policy number
GET "http://<url>:<port>/api/valuations/<policy number>"

# return one insurance policy with the policy number and start date
GET "http://<url>:<port>/api/valuations/<policy number>/startdate/<start date>"

# updating information for that ONE policy with policy number and start date
PUT "http://<url>:<port>/api/valuations/<policy number>/startdate/<start date>"

我的回答基于基于名词的 API 网址,而不是基于动词。 有关更多信息:Confusion Between Noun vs. Verb in Rest URLs


如果您将开始日期作为 POST 参数传递,您应该将其绑定到视图模型:

class ValuationPolicyStartDateViewModel
{
   public DateTime? StartDate { get; set; }
}

// then in your controller
// PUT StartDate = "01/22/2018" will then be bound to your  view model
public IHttpActionResult UpdatePolicyByStartDate(string policyNumber, [FromBody] ValuationPolicyStartDateViewModel viewModel)
{
   ... code that validates etc ...
}

TL;DR

如果 /api/valuation/<policy number> returns 1 保单,请使用示例中的选项 2 并使 "valuation" 复数。

如果 /api/valuation/<policy number> returns 超过 1 份保单,那么您应该做几件事:将 valuation 更改为 valuations 并添加 startdate 作为过滤器变量。