Hello,
Controller/Service scaffolding in SnapDevelop API generates HttpPost method that can also be used for HttpPut, i.e. for updating only one row of a given model (which is a must for non-PB REST client):
// Controller
[HttpPut]
public async Task<ActionResult<int>> UpdateAsync([FromBody]Employee employee)
//Service
public async Task<int> UpdateAsync(Employee employee,CancellationToken cancellationToken)
{
var dataStore = await this.RetrieveByKeyAsync(new object[] {employee.emp_id},cancellationToken);
dataStore.SetModel(0, employee);
return await dataStore.UpdateAsync(cancellationToken);
}
Now, cients can send JSON to http://localhost/api/employee/1 as PUT request and the DB update works fine, because .NET datastore SetModel() sets the data of Employee object to the first row of the DataStore:
{
emp_id: 1,
emp_lname: "Smith",
emp_fname: "John",
emp_deptid: 100,
[...]
}
Instead of PUT, (non-PB) clients better send a PATCH verb because it allows for partial updates:
{
emp_id: 1,
emp_deptid: 200
}
but with this body the Controller returns all the fields in the model object that are nulls except emp_deptid, which makes sense since it is saying I want a Models.Employee object.
Is there a way to detect which properties have actually been sent in the JSON request so I can update only those fields?
The "silly" solution is to test all properties in the JSON and keep old values in the TModel (e.g. Employee) if not sent by the client, but this requires per-model implementation.
Am I missing a .NET datastore method that does this trick?
Microsoft suggests to use JsonPatchDocument in the Patch action of a Controller, but this goes beyond the datastore API:
[FromBody]JsonPatchDocument<Employee> employee
Thanks,
.m
For the client side, you can find a library that supports JSON-Patch for many languages. Refer to: http://jsonpatch.com/#Libraries
For the server-side, there are some flexible solutions to know which properties have been changed according to the JSON data. E.g.:
1) Parse the HttpContext.Request.Body JSON string directly.
2) Use the IDataUnpacker (https://docs.appeon.com/snapobjects/3.1/api_reference/SnapObjects.Data/IDataUnpacker/IDataUnpacker.html) provided in SnapObjects as the parameter type of the Action in the Controller to help process JSON quickly.
3) Implements a new generic type to present a model entry with the state (similar to IModelEntry<T>: https://docs.appeon.com/snapobjects/3.1/api_reference/SnapObjects.Data/IModelEntry1/IModelEntry.html).
Then support receiving this custom type of parameter in your action method, refer to:
https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding?view=aspnetcore-3.1
Regards, Logan