Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explore usage of INotifyPropertyChanged with NSwag clients #1577

Open
bkoelman opened this issue Jun 26, 2024 · 2 comments
Open

Explore usage of INotifyPropertyChanged with NSwag clients #1577

bkoelman opened this issue Jun 26, 2024 · 2 comments
Labels

Comments

@bkoelman
Copy link
Member

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.

@bkoelman
Copy link
Member Author

bkoelman commented Jul 9, 2024

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.

@bkoelman
Copy link
Member Author

Request tracked at RicoSuter/NJsonSchema#1717.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

1 participant