question

wavemaster avatar image
0 Votes"
wavemaster asked RenaNi-MSFT edited

HTTP PATCH - one DTO to patch multiple Entities

My current implementation has two http.PatchAsync() calls to the Web API, i.e. to multiple controller action methods, one for each Entity.

Thought that I could improve on this by sending one DTO containing the data the needs to be updated for multiple Entities, only one packet at risk of loss vs. multiple.

Now I have hit a road block as I cannot find how to use the same JsonPatchDocument for several Entities

Code so far:

 [Route("UpdatePartial/{id}")]  /
         [HttpPatch]
         public async Task<IActionResult> Patch(int id, bool hasQbWc, [FromBody] JsonPatchDocument<TxnBillingPatch> txnPatch)
         {
             if (txnPatch == null) { return BadRequest(); }
                
             var theTxn = context.Transactions.FirstOrDefault(t => t.TransactionId == id);
    
             if (theTxn == null) { return NotFound(); }
             **txnPatch.ApplyTo(theTxn, ModelState);**
    
             var isValid = TryValidateModel(theTxn);
             if (!isValid) { return BadRequest(ModelState);  }
                            
             //await context.SaveChangesAsync();
             return NoContent();
         }


Squiggles on the bolded line with "cannot convert from Transaction (the Entity) to TxnBillingPatch (the DTO)

dotnet-aspnet-core-webapi
· 8
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

If it won't do an implicit Type Casting / Automatic Type Conversion, then you're going to gave to map out the object to the other object.

0 Votes 0 ·

Do try this approach when using **HTTP Pacth in API calls**.



0 Votes 0 ·

@yogyogi

Looked at your link, that is just a single Entity Patch

Mine is where I need to Patch 2 or 3 entities, hopefully from a single DTO

0 Votes 0 ·

@DuaneArnold-0443


Irregardless of the mapping, can a single patchDoc be used for multiple Entities?

Like so:

 patchDTO.ApplyTo(theProvider, ModelState);
 patchDTO.ApplyTo(theTxn, ModelState);

As far as I know I can only send one patchDoc to the Patch action method, right?

0 Votes 0 ·

I couldn't tell. What was you justification to take this patch approach?

0 Votes 0 ·

For Patch? Large tables mostly.

0 Votes 0 ·
Show more comments

1 Answer

RenaNi-MSFT avatar image
0 Votes"
RenaNi-MSFT answered RenaNi-MSFT edited

Hi @wavemaster ,

You need change like below:

     [Route("UpdatePartial/{id}")]
     [HttpPatch]
     public async Task<IActionResult> Patch(int id, bool hasQbWc, [FromBody] JsonPatchDocument<TxnBillingPatch> txnPatch)
     {
         if (txnPatch == null) { return BadRequest(); }
         var theTxn = new Transaction() { Id = 1, TransName = "trans1" };
            
        //add this....
         var data = new TxnBillingPatch();      
         data.Transaction = theTxn;
         txnPatch.ApplyTo(data, ModelState); 
    
         var isValid = TryValidateModel(theTxn);
         if (!isValid) { return BadRequest(ModelState); }
    
         //await context.SaveChangesAsync();
         return new ObjectResult(data);
     }

JSON patch example:

 [
     {
         "op":"add",
         "path":"/TestViewModel",
         "value":[{
             "id":1,
             "testName":"aa"
         }]
     }
 ]

Result:

 {
     "transaction": {
         "id": 1,
         "transName": "trans1"
     },
     "testViewModel": [
         {
             "id": 1,
             "testName": "aa"
         }
     ]
 }



If the answer is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Best Regards,

Rena





· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Rena,

Just to make sure...... my PatchDoc has properties of two different entities Transaction and Provider.

 JsonPatchDocument<TxnBillingPatch> patchDocTxnX = new JsonPatchDocument<TxnBillingPatch>();
             patchDocTxnX.Replace(p => p.NextBillNo, theProvider.NextBillNo);
             patchDocTxnX.Replace(p => p.IsBilled, true);

             patchDocTxnX.Replace(p => p.BDate, billDate);
             if (theProvider.HasQbWc) { patchDocTxnX.Replace(p => p.AddTransaction, true); }
             var serializedItem = JsonConvert.SerializeObject(patchDocTxnX);
    
             var response = await httpClient.PatchAsync($"{baseUrl}/api/Txn/UpdatePartialX/{txns.ElementAt(0).TransactionId}",
             new StringContent(serializedItem, System.Text.Encoding.Unicode, "application/json-patch+json"));
    
             var data = await response.Content.ReadAsStringAsync();

I
In my mind I need to make two (2) ApplyTo(), so I do not see where you are going with new Transaction lines 7 - 11

Please clarify.

0 Votes 0 ·

Hi @wavemaster, sorry for late reply. TxnBillingPatch is a view model with several models in it. In my scenario, just need txnPatch.ApplyTo(data, ModelState); then it will add or modify (or did any other operations ) all the data you posted to the backend. Could you please share your detailed scenario? Which operation you want to did for the two models?

0 Votes 0 ·

This is what my Transaction Entity PatchDoc looks like:

 JsonPatchDocument<**Transaction**> patchDocTxn = new JsonPatchDocument<Transaction>();
             patchDocTxn.Replace(p => p.BillNo, theProvider.NextBillNo);
             patchDocTxn.Replace(p => p.IsBilled, true);
             patchDocTxn.Replace(p => p.Link, link);
             patchDocTxn.Replace(p => p.TinyLink, tinylink);
             patchDocTxn.Replace(p => p.PayMethod, payMethod);
             patchDocTxn.Replace(p => p.Bdate, billDate);
    
             serializedItem = JsonConvert.SerializeObject(patchDocTxn);
             response = await httpClient.PatchAsync($"{baseUrl}/api/Txn/UpdatePartial/{txns.ElementAt(0).TransactionId}",

Then there is a second patchDoc for the ProviderEntity:
JsonPatchDocument<Provider> patchDocProvider = new JsonPatchDocument<Provider>();
patchDocProvider.Replace(p => p.NextBillNo, theProvider.NextBillNo++);
serializedItem = JsonConvert.SerializeObject(patchDocProvider);

         response = await httpClient.PatchAsync($"{baseUrl}/api/Provider/UpdatePartial/{theProvider.ProviderId}",



These are all "Replace"

And I have two action methods, one for each Entity.

0 Votes 0 ·
Show more comments