目前推荐的使用Web API执行部分更新的方法是什么?

akn*_*ds1 22 rest updates asp.net-web-api

我想知道如何使用ASP.NET Web API的RESTful接口实现部分更新?比方说,我们通过以下结构的线路传递对象:

public class Person {
    public int Id { get; set; }
    public string Username { get; set; }
    public string Email { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

如何支持一次更新一部分内容Person,例如Email属性?是建议通过OData和PATCH动词来实现这个,还是自己实现PATCH会更好?

Fil*_*p W 31

目前最新的Web API 稳定版本(2012年8月起)没有支持.因此,如果您只想使用Web API RTM,则必须自己实现整个管道.

话虽如此,OData预发布包通过新Delta<T>对象非常好地支持部分更新.目前,Microsoft.AspNet.WebApi.OData包已经是RC版本(0.3),可以从这里获得:http://www.nuget.org/packages/Microsoft.AspNet.WebApi.OData

安装后,您可以相应地使用它:

[AcceptVerbs("PATCH")]
public void Patch(int id, Delta<Person> person)
{
    var personFromDb = _personRepository.Get(id);
    person.Patch(personFromDb);
    _personRepository.Save();
}
Run Code Online (Sandbox Code Playgroud)

你会从客户端这样称呼它:

$.ajax({
    url: 'api/person/1',
    type: 'PATCH',
    data: JSON.stringify(obj),
    dataType: 'json',
    contentType: 'application/json',
    success: function(callback) {            
       //handle errors, do stuff yada yada yada
    }
});
Run Code Online (Sandbox Code Playgroud)

这样做的明显优势在于它适用于任何财产,您无需关心是否更新Email或其他内容Username.

您可能还想查看这篇文章,因为它显示了一种非常类似的技术http://techbrij.com/http-patch-request-asp-net-webapi

编辑(更多信息): 为了只使用PATCH,除了添加OData包之外,您不需要启用与OData相关的任何内容来访问 Delta<TEntityType>对象.

然后你可以这样做:

public class ValuesController : ApiController
{
    private static List<Item> items = new List<Item> {new Item {Id = 1, Age = 1, Name = "Abc"}, new Item {Id = 2, Age = 10, Name = "Def"}, new Item {Id = 3, Age = 100, Name = "Ghj"}};

    public Item Get(int id)
    {
        return items.Find(i => i.Id == id);
    }

    [AcceptVerbs("PATCH")]
    public void Patch(int id, Delta<Item> item)
    {
        var itemDb = items.Find(i => i.Id == id);
        item.Patch(itemDb);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你的项目是,让我们说:

{
    "Id": 3,
    "Name": "hello",
    "Age": 100
}
Run Code Online (Sandbox Code Playgroud)

您可以通过以下方式修补/api/values/3:

{
    "Name": "changed!"
}
Run Code Online (Sandbox Code Playgroud)

这将正确更新您的对象.

Delta<TEntity>将跟踪您的变化.它是一个动态类,充当您的Type的轻量级代理,并将理解原始对象(即来自DB)与客户端传递的对象之间的差异.

这不会以任何方式影响API的其余部分(当然除了用更新的DLL替换DLL以促进OData包依赖性).

我添加了一个示例项目来演示PATCH + Delta的工作 - 你可以在这里抓住它(it.s VS2012)https://www.dropbox.com/s/hq7wt3a2w84egbh/MvcApplication3.zip

  • 实际上我的评论是错误的:)你可以使用Patch + Delta而不启用OData位.Delta <T>只是一个跟踪依赖关系的代理.我编辑了答案并添加了一个示例项目 (2认同)
  • 也许你应该说它只适用于非原始数据类型.它无法修补int值(演示中的Age). (2认同)