ASP.NET Web API 2和部分更新

Eug*_*kov 6 c# asp.net patch asp.net-web-api asp.net-web-api2

我们正在使用ASP.NET Web API 2并希望以下列方式公开部分编辑某些对象的能力:

HTTP PATCH /customers/1
{
  "firstName": "John",
  "lastName": null
}
Run Code Online (Sandbox Code Playgroud)

...设置firstName"John"lastNamenull.

HTTP PATCH /customers/1
{
  "firstName": "John"
}
Run Code Online (Sandbox Code Playgroud)

......为了以防更新firstName"John",不碰lastName的.假设我们有许多我们想要用这种语义更新的属性.

这是由OData行使的非常方便的行为.

问题是默认的JSON序列化器null在两种情况下都会出现,因此无法区分.

我正在寻找一些方法来使用某种包装器(带有值和标志设置/未设置)来注释模型,这样可以看到这种差异.任何现有的解决方案?

Eug*_*kov 4

我知道已经给出的答案已经涵盖了所有方面,但只是想分享我们最终所做的事情以及似乎对我们非常有效的事情的简要总结。

创建通用数据合约

[DataContract]
public class RQFieldPatch<T>
{
    [DataMember(Name = "value")]
    public T Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

为补丁请求创建临时数据契约

示例如下。

[DataContract]
public class PatchSomethingRequest
{
    [DataMember(Name = "prop1")]
    public RQFieldPatch<EnumTypeHere> Prop1 { get; set; }

    [DataMember(Name = "prop2")]
    public RQFieldPatch<ComplexTypeContractHere> Prop2 { get; set; }

    [DataMember(Name = "prop3")]
    public RQFieldPatch<string> Prop3 { get; set; }

    [DataMember(Name = "prop4")]
    public RQFieldPatch<int> Prop4 { get; set; }

    [DataMember(Name = "prop5")]
    public RQFieldPatch<int?> Prop5 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

商业逻辑

简单的。

if (request.Prop1 != null)
{
    // update code for Prop1, the value is stored in request.Prop1.Value
}
Run Code Online (Sandbox Code Playgroud)

Json格式

简单的。不像“JSON Patch”标准那么广泛,但涵盖了我们所有的需求。

{
  "prop1": null, // will be skipped
  // "prop2": null // skipped props also skipped as they will get default (null) value
  "prop3": { "value": "test" } // value update requested
}
Run Code Online (Sandbox Code Playgroud)

特性

  • 简单的合约,简单的逻辑
  • 无序列化定制
  • 支持空值分配
  • 涵盖任何类型:值、引用、复杂的自定义类型等等