0

I have an app that has an entity entitled, "Invoice". Within the Invoice entity, I have a reference to a collection for another entity entitled, "InvoiceLine".

I am using SyncFusion's DataGrid along with DataManager to perform CRUD operations. When I click on an invoice in the datagrid, it displays a component containing the relevant information. The invoice contains an invoice line component. When I make a change to an invoice line, the UI reflects the changes. I have also verified that the invoice line within the invoice line collection within the invoice reflects the changes.

The issues is when I click save, the changes are not carried through to the controller on the server-side.

// relevant line within the invoice entity class
// Navigation property
        public List<InvoiceLine>? InvoiceLines
        {
            get => GetPropertyValue<List<InvoiceLine>?>();
            set => SetPropertyValue(value);
        }
// invoice data manager class
namespace AccountsReceivable.Client.DataAdaptor
{
    public class InvoicesDataManager : SfDataManager
    {
        private IServerApiService _serverApiService = default!;

        [Inject]
        private IServerApiService ServerApiService
        {
            get => _serverApiService;
            set
            {
                if (_serverApiService != value)
                {
                    _serverApiService = value;
                    OnServerApiServiceChanged();
                }
            }
        }

        public InvoicesDataManager()
        {
            Adaptor = Syncfusion.Blazor.Adaptors.ODataV4Adaptor;
            this.EnableCaching = true;
        }
        // Set data manager url values
        private void OnServerApiServiceChanged()
        {
            // main url
            const string apiUrl = "api/Invoices";
            // Instantiate http instance
            HttpClientInstance = ServerApiService.HttpClientInstance;
            // Set base url
            Url = ServerApiService.GetApiUrl(apiUrl);
            // Set saving url
            UpdateUrl = ServerApiService.GetApiUrl($"{apiUrl}/save");
            // Set deletion url
            RemoveUrl = ServerApiService.GetApiUrl($"{apiUrl}/delete");
        }

        protected override void OnInitialized()
        {
            OnServerApiServiceChanged();
            base.OnInitialized();
        }
    }
}
// Controller code...the values argument contains the changes that have been made.
// PATCH: api/invoices/save
        [HttpPatch("save({invoiceId})")]
        [AuthorizeScope(AuthorizationScope.UpdateInvoice)]
        public async Task<ActionResult> Patch([FromRoute] int invoiceId, [FromBody] IDictionary<string, JsonDocument>? values, CancellationToken ct)
        {
            try
            {
                Invoice? invoice = await _invoiceDataProvider.GetItemAsync(invoiceId);
                if (invoice != null)
                {
                    values?.Patch(invoice);

                    await _invoiceDataProvider.SaveAsync(invoice);
                }

                return Ok(ApiResponse.OkResponse(invoice));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Invoice Error");
                return BadRequest(new ApiResponse(ApiStatusCodes.UnhandledError, ex.Message));
            }
        }
Clay Hess
  • 228
  • 6
  • 24

1 Answers1

0

You are facing difficulties due to the updated values sent to server as Patch request. By default ODataV4 accepts Patch method to update the records in database. PATCH request is similar to PUT method where only difference is that in PATCH request the only the modified properties [(i.e.) only updated properties] will be sent to API server. All other default properties will ignored in PATCH request. So, I suspect that you are facing issue while updating your Navigation property.

Consider the below example of Order class.


public class Order

   {

       [Key]

       public int? OrderID { get; set; }

       public string CustomerID { get; set; }

       public DateTime? OrderDate { get; set; }

       public double? Freight { get; set; }

   }

List is bound to Grid using ODataV4 adaptor and DataManager, in that CustomerID column alone edited in the first record. While saving the changes PUT request will be sent to the API server with the entire object consisting { OrderID, CustomerID, OrderData, Freight } all these properties.

But in PATCH request, only the modified property (CustomerID) alone will be considered and sent to the API server for PATCH operation. This is the difference between PUT and PATCH requests.

Please refer to the below online reference between PUT and PATCH requests.

Use of PUT vs PATCH methods in REST API real life scenarios

https://rapidapi.com/blog/put-vs-patch/

user12702211
  • 111
  • 3
  • Thank you for your post. I am aware of the differences between PUT and PATCH. My issue is that I make changes to a navigational property and those are not being recognized and sent to the server-side controller. I am not sure why my changes to a navigational property are not being "caught"? – Clay Hess Mar 08 '23 at 19:38