简体   繁体   中英

Update only certain properties with Simple.OData.Client

I'm using Simple.OData.Client and I would like to update certain properties of an entity.

Let's say I have following class in C#:

[DataContract(Name = "entity")]
public class MyEntity
{
        [DataMember(Name = "propertyA")]
        public string MyPropertyA { get; set; }

        [DataMember(Name = "propertyB")]
        public string MyPropertyB { get; set; }
}

I'm trying to update propertyA like this:

await _simpleOdataClient.For<MyEntity>()
                  .Key(key)
                  .Set(new MyEntity
                  {
                    MyPropertyA = "test"
                  })
                  .UpdateEntryAsync();

I took this as an example: https://github.com/object/Simple.OData.Client/wiki/Updating-entries

My problem is that sends a PUT request with propertyA=test but also propertyB=null. It tries to set null value for the property I don't want to change.

Is it possible to only update certain properties and to send HTTP PATCH in the OData request?

You should use PATCH instead of PUT.

The HTTP Standard says:

A successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being sent in a 200 (OK) response.

So if you issue a PUT with just MyPropertyA in the request then a subsequent GET should return an Entity with MyPropertyB as null .

Primarily, the OData v4 Standard says:

Services that support PUT MUST replace all values of structural properties with those specified in the request body. Missing non-key, updatable structural properties not defined as dependent properties within a referential constraint MUST be set to their default values .

While you may be able to get the client to not send MyPropertyB , a proper OData server MUST interpret that as a request to set the value to be default (null).

You should use an anonymous object for doing that or find some way to configure the client's serializer to ignore default values (eg null on a ref type).

await _simpleOdataClient.For<MyEntity>()
                  .Key(key)
                  .Set(new
                  {
                    MyPropertyA = "test"
                  })
                  .UpdateEntryAsync();

You can achieve this with the typed fluent API.

You have to select the fields explicitly for reads (.Select) and set them explicitly on writes.(.Set) to prevent the whole structure being sent.

I think you are almost there.. Instead of .Set(new MyEntity use .Set(new .

I also use a populated entity instance and simplified .Set

              .Set(new 
              {
                myEntity.MyPropertyA,
              })

is equivalent to

              .Set(new 
              {
                MyPropertyA = myEntity.MyPropertyA,
              })

All up then this should work. Unless the DataContract is somehow causing an issue. In my working example there isn't DataContract attributes for the class. Verified with Fiddler that only specified fields are sent ( in my code ).

 var myEntity = new MyEntity() 
 {
    MyPropertyA = "test"
 };

 await _simpleOdataClient.For<MyEntity>()
              .Key(key)
              .Set(new 
              {
                myEntity.MyPropertyA,
              })
              .UpdateEntryAsync();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM