Обновите только определенные свойства с помощью 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();
Другие вопросы по тегам