Ответ 1
Нет поддержки в текущей последней стабильной версии Web API (с августа 2012 года). Поэтому, если все, что вы хотите использовать, это RTM для веб-API, вам придется реализовать всю сантехнику самостоятельно.
С учетом этого, пакет OData preerelease поддерживает частичные обновления очень хорошо с помощью нового объекта 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();
}
И вы бы назвали его от клиента следующим образом:
$.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
}
});
Очевидным преимуществом этого является то, что он работает для любого свойства, и вам не нужно заботиться о том, обновляете ли вы Email
или Username
или еще что-то.
Вы также можете посмотреть этот пост, поскольку он показывает очень похожую технику http://techbrij.com/http-patch-request-asp-net-webapi
EDIT (подробнее):
Чтобы просто использовать 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);
}
}
Если ваш предмет, скажем:
{
"Id": 3,
"Name": "hello",
"Age": 100
}
Вы можете PATCH на /api/values/3
с помощью:
{
"Name": "changed!"
}
и это будет правильно обновлять ваш объект.
Delta<TEntity>
будет отслеживать изменения для вас. Это динамический класс, который действует как легкий прокси для вашего Типа и будет понимать различия между исходным объектом (т.е. Из БД) и тем, который был передан клиентом.
Это НЕ будет влиять на остальную часть вашего API каким-либо образом (за исключением, конечно, замены библиотек DLL более новыми для облегчения зависимостей пакета OData).
Я добавил пример проекта, чтобы продемонстрировать работу PATCH + Delta - вы можете его захватить здесь (it.s VS2012) https://www.dropbox.com/s/hq7wt3a2w84egbh/MvcApplication3.zip