Explore usage of INotifyPropertyChanged with NSwag clients
bkoelman opened this issue · 2 comments
If possible, this smoothens the experience of partial post/patch for atomic operations. Otherwise, the existing extension method must take the operation index as a parameter.
This would be great to use for partial patch, where sending "firstname": null means something different than omitting it.
Unfortunately, this isn't currently possible, because the client code generated by NSwag performs a comparison before raising the INotifyPropertyChanged.PropertyChanged event. For example:
<PropertyGroup>
<NSwagClassStyle>INPC</NSwagClassStyle>
</PropertyGroup>Generates the following code:
[Newtonsoft.Json.JsonProperty("firstName", Required = Newtonsoft.Json.Required.Default,
NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string? FirstName
{
get { return _firstName; }
set
{
if (_firstName != value) // <----- this check must be removed, so we can detect null/default assignments
{
_firstName = value;
RaisePropertyChanged();
}
}
}As a workaround, we'd need to ship a custom template for NJsonSchema, based on the default template.
If we did, the following would work:
var updatePersonRequest = new UpdatePersonRequestDocument
{
Data = new DataInUpdatePersonRequest
{
Id = "1",
// This line results in sending "firstName: null" instead of omitting it.
Attributes = new TrackChangesFor<AttributesInUpdatePersonRequest>(_apiClient)
{
Initializer =
{
FirstName = null,
LastName = "Knight Rider"
}
}.Initializer
}
};
var response = await ApiResponse.TranslateAsync(async () =>
await _apiClient.PatchPersonAsync(updatePersonRequest.Data.Id, updatePersonRequest));Likewise, it can now be used in an atomic:operations request:
var operationsRequest = new OperationsRequestDocument
{
Atomic_operations =
[
new CreatePersonOperation
{
Data = new DataInCreatePersonRequest
{
Lid = "new-person",
// This line results in sending "firstName: null" instead of omitting it.
Attributes = new TrackChangesFor<AttributesInCreatePersonRequest>(_apiClient)
{
Initializer =
{
FirstName = null,
LastName = "Cinderella"
}
}.Initializer
}
}
]
};
var response = await _apiClient.PostOperationsAsync(operationsRequest, cancellationToken);Unfortunately, the template we'd need to ship is rather large. We'd need to replicate any changes to it, which is a maintenance burden on our side. But what's worse is that our NuGet package becomes indirectly dependent on specific NSwag versions.
Request tracked at RicoSuter/NJsonSchema#1717.