rest - 如何使用restful API 实现对象属性更新?

标签 rest servicestack updates

使用 ServiceStack(面向消息的 RESTful Web 服务)实现对象属性更新的正确方法是什么?

如果客户端需要更新 Foo.bar 并且只有 Foo 的 id。

我应该接受包含 Foo id 和 Foo.bar 值的 FooBarUpdate 请求对象吗?
这意味着我必须为每个属性更新创建单独的请求,或者至少为那些我希望更新的请求(或它们的组合)。这似乎也不符合 RESTful 标准。

或者,如果我接受包含具有更新属性的整个 Foo 的 Foo 请求对象,客户端将首先需要检索 Foo,然后服务将检查哪些属性已更新。这似乎是不必要的开销。

最后,如果我接受 Foo 请求但只有 id 和修改后的属性值 (Foo.bar),则 Foo 对象是不完整的,根据其他帖子,这可能会导致混淆,有人认为它是一个完整的对象。

最佳答案

如何处理 RESTful 更新:
BarFoo 上的个人属性(property)那么没有理由你不能只拥有一个 UpdateFooRequest包含更新的 Bar .
像这样:

[Route("/foo/{Id}", "POST")]
public class UpdateFooRequest
{
    public int Id { get; set; }
    public Bar Bar { get; set; }
}
但是如果 Bar是一个集合,使得 Foo 是:
public class Foo
{
    public int Id { get; set; }
    public Bar[] Bar { get; set; }
}
然后更安静的方式更新 Bar Foo上的项目是引用bar的实例通过 Foo路线。但是您需要知道条形图的 id,(或集合中相对于它的索引 Foo )。
[Route("/foo/{FooId}/bar/{Id}", "POST")]
public class UpdateFooBarRequest : Bar
{
    public int FooId { get; set; }
}

在服务器处理部分更新
为了解决这些问题:

Alternatively, if I accept a Foo request object that includes the whole Foo with the updated properties, the client would first need to retrieve Foo and then the service would check which properties were updated. This seems like an unnecessary overhead.


唯一一次您需要关注一个整体 Foo是什么时候Foo正在创建,它将拥有自己的路线。所以这里应该没什么好担心的。
[Route("/foo", "POST")]
public class CreateFooRequest
{
    ...
}
Foo正在更新您将发布到现有的 Foo 路由,如 /foo/123 :
[Route("/foo/{Id}", "POST")]
public class UpdateFooRequest
{
    public int Id { get; set; }
    ...
}
最终,您的服务应该能够指示 ORM 仅更新包含在请求中的字段的更改。因此,如果请求只有几个更改,那么 ORM 将处理它。
例如,ORMLite 更新很简单:
db.Update<Foo>(updateFooRequest);
这将创建一个 SQL UPDATEId 标识的行上仅使用在请求中找到的字段;
如全Foo发送然后允许 ORM 将其视为更改许多字段,该记录将被覆盖。您可以按照您的建议在更新之前查找记录并确定更改的字段,但正如您所说,这是不必要的开销。
通常,如果您的更新方法处理部分更改,则发送整个 Foo应该没有问题,但理想情况下,客户端应该只发送更改。

Lastly, if I accept a Foo request but with only the id and the modified property value (Foo.bar), the Foo object is incomplete and according to other posts, this can lead to confusion where someone assumes it's a full object.


最后一行 where someone assumes it's a full object ,有点担心。 update 路由应该只用于更新,你不应该在这里使用完整的对象。更新方法应该期待请求 Foo是部分的,并按照我上面的解释进行处理。

我想你应该read up on ORMLite它展示了如何将部分更新应用于现有数据的一些很好的例子。虽然您不必选择 ORM,但基本概念适用于其他 ORM,我认为这很好地说明了它们。

解决更新项目 BarFoo 上的集合中按名字:
这样做是非常规的。使用有意义的值(例如 Name)的一个缺点是您将无法轻松更改此属性 - 因为它是一个标识符。如果它是静态的,那就没问题了。
所以Foo看起来像这样:
public class Foo
{
    public int Id { get; set; }
    public Bar[] Bar { get; set; }
}
让我们假设 Bar
public class Bar
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Baz { get; set; }
    public bool IsEnabled { get; set; }
}
如果我使用 Name而不是 Id Bar 要更新,我无法更改 Name属性,因为那时我不知道要更新哪个 Bar。我现在需要一条全新的路线来处理更改 Bar 的名称。
如果您决定将其用作集合中的标识符,您可以执行以下操作:
[Route("/foo/{FooId}/bar/{Name}", "POST")]
public class UpdateFooBarRequest : Bar
{
    public int FooId { get; set; }
}
所以用更新的 Baz = 13 更新 Foo 123和 IsEnabled = false在名为“鲍勃”的酒吧
POST /foo/123/bar/Bob
{
    Baz: 13,
    IsEnabled: false
}
在您的操作方法中,您只需要更新与名称“Bob”匹配且具有 Foo 123 的项目。在 ORMLite 中,它看起来像这样:
db.Update(updateBarRequest, p => p.FooId == updateBarRequest.FooId && p.Name == updateBarRequest.Name);
但这样做意味着你不能这样做:[Route("/foo/{FooId}/bar/{Id}", "POST")][Route("/foo/{FooId}/bar/{Name}", "POST")]因为路由器不会知道您是否正在传递 IdName那么你必须做非常规的 REST,比如 [Route("/foo/{FooId}/bar/byName-{Name}", "POST")] .
我希望这有帮助。

关于rest - 如何使用restful API 实现对象属性更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20843842/

相关文章:

django - 在Django REST Framework中限制每页的项目

servicestack - OrmLite 通过多列连接表

azure - Update 3 后 Visual Studio 2013 Premium 解决方案加载错误

java - 在 for 循环中更新列表值失败但在具有对象值的列表中成功

json - 我可以/应该使用 YAML 作为 RESTful Web 服务中的有效负载吗?

c# - 如何在 C# 中编写 REST Get-Request?

java - 如何将 InputStream 传递给 REST 服务 POST 方法

web-services - ServiceStack 跨平台互操作性

session - 无法使用 Servicestack 在 Redis 上设置 session 信息

google-chrome - Chrome 扩展程序多久自动更新一次?