Обновите только определенные свойства с помощью Simple.OData.Client
Я использую Simple.OData.Client, и я хотел бы обновить некоторые свойства объекта.
Допустим, у меня есть следующий класс в C#:
[DataContract(Name = "entity")]
public class MyEntity
{
[DataMember(Name = "propertyA")]
public string MyPropertyA { get; set; }
[DataMember(Name = "propertyB")]
public string MyPropertyB { get; set; }
}
Я пытаюсь обновить свойство A следующим образом:
await _simpleOdataClient.For<MyEntity>()
.Key(key)
.Set(new MyEntity
{
MyPropertyA = "test"
})
.UpdateEntryAsync();
Я взял это в качестве примера: https://github.com/object/Simple.OData.Client/wiki/Updating-entries
Моя проблема заключается в том, что отправляет запрос PUT с propertyA=test, но также propertyB=null. Он пытается установить нулевое значение для свойства, которое я не хочу менять.
Можно ли обновить только определенные свойства и отправить HTTP PATCH в запросе OData?
3 ответа
Вы должны использовать PATCH вместо PUT.
HTTP Стандарт говорит:
Успешный PUT данного представления предполагает, что последующий GET для того же целевого ресурса приведет к отправке эквивалентного представления в ответе 200 (OK).
Итак, если вы выдадите PUT только
MyPropertyA
в запросе последующий GET должен вернуть Entity с as
null
.
В первую очередь, стандарт OData v4 гласит:
Службы, поддерживающие PUT, ДОЛЖНЫ заменять все значения структурных свойств значениями, указанными в теле запроса. Для отсутствующих неключевых обновляемых структурных свойств, не определенных как зависимые свойства в рамках реляционного ограничения, ДОЛЖНЫ быть установлены значения по умолчанию .
Хотя вы можете заставить клиента не отправлять
MyPropertyB
, надлежащий сервер OData ДОЛЖЕН интерпретировать это как запрос на установку значения по умолчанию (null).
Для этого вам следует использовать анонимный объект или найти какой-либо способ настроить сериализатор клиента на игнорирование значений по умолчанию (например, null для типа ref).
await _simpleOdataClient.For<MyEntity>()
.Key(key)
.Set(new
{
MyPropertyA = "test"
})
.UpdateEntryAsync();
Вы можете добиться этого с помощью типизированного свободного API.
Вы должны явно выбрать поля для чтения (.Select) и установить их явно для записи.(.Set), чтобы предотвратить отправку всей структуры.
Думаю, вы почти у цели.. Вместо .Set(новый MyEntity используйте .Set (new.
Я также использую экземпляр заполненного объекта и упрощаю.Set
.Set(new
{
myEntity.MyPropertyA,
})
эквивалентно
.Set(new
{
MyPropertyA = myEntity.MyPropertyA,
})
Все должно работать. Если только DataContract каким-то образом не вызывает проблемы. В моем рабочем примере нет атрибутов DataContract для класса. Проверено Fiddler, что отправляются только указанные поля (в моем коде).
var myEntity = new MyEntity()
{
MyPropertyA = "test"
};
await _simpleOdataClient.For<MyEntity>()
.Key(key)
.Set(new
{
myEntity.MyPropertyA,
})
.UpdateEntryAsync();