json-api-dotnet / JsonApiDotNetCore

A framework for building JSON:API compliant REST APIs using ASP.NET and Entity Framework Core.
https://www.jsonapi.net
MIT License
662 stars 160 forks source link

Atomic Operations, always getting 'null' on IList<OperationContainer> operations #1566

Open alnotas opened 2 weeks ago

alnotas commented 2 weeks ago

Greetings everyone, and thank you for your incredible work.

I'm trying for the first time to use the feature of Atomic Operations and though I'm certain I have done everything right, I keep getting bogus errors. I have implemented several CRUD actions for my resources that work well for the past year. Now I'm trying to find out how to perform Bulk actions, starting with the simplest scenario, a single "add" operation. I've changed the content type to application/vnd.api+json; ext="https://jsonapi.org/ext/atomic" I've created an sealed OperationsController that derives from JsonApiOperationsController and I have overridden the method PostOperationsAsync just to be able to debug (I know it is not necessary to override it).

image

I have a resource of type "ProductPricelistItem" and the following is my pretty simple payload: { "atomic:operations": [ { "op": "add", "data": { "type": "ProductPricelistItem", "attributes": { "priceType": "CurrencyAmount" } } } ] }

Upon executing POST I get the error: 500 "ValidationVisitor exceeded the maximum configured validation depth '32' when validating property 'PublicName' on type 'JsonApiDotNetCore.Resources.Annotations.ResourceFieldAttribute'. This may indicate a very deep or infinitely recursive object graph. Consider modifying 'MvcOptions.MaxValidationDepth' or suppressing validation on the model type."

image

After following the messages advice (and as suggested elsewhere) I go to my services configuration and add services.AddMvc().AddMvcOptions(options => { options.MaxValidationDepth = 99999; });

That seems to eliminate the particular problem and I see the debugger continues to PostOperationsAsync. But there are two problems. 1) The "[FromBody] IList operations" parameter comes as 'null' 2) All my other already established and working endpoints, stop to work and I get a huge error image

I also tried adding the Attribute [ValidateNever] at my Resource but that doesn't seem to do anything. Also, as suggested elsewhere, I tried adding options.MaxModelValidationErrors = 999999; at my parameters but nothing.

I've tried several tweaks in my Payload, hoping it may have something to do with it but upon trying another scenario, where I omit the setup of MaxValidationDepth and I put a deliberate error in "attributes", writing the "priceType" as "priceTypeQQQ", the parser informs me the following, which is correct which makes me think that my original Payload is correct because I don't get that error with "priceType", only the "ValidationVisitor" error. Upon setting the MaxValidationDepth I don't get the parsing error but anyway the operations parameter always comes as 'null'

image

Am I missing something? What could be the cause of the 'null' in operations parameter and how can I overcome the ValidatorVisitor problem and still keep my other endpoints working?

Please advise

VERSIONS USED

bkoelman commented 2 weeks ago

Hi @alnotas, thanks for reaching out.

I vaguely recall a similar problem, which was caused by calling unnecessary boilerplate methods at startup that mixed things up, such as AddControllers. Can you share what your startup code looks like?

alnotas commented 2 weeks ago

@bkoelman That's it... Upon removing 'AddControllers' everything worked. Thank you so much And I don't even need to set up the MaxValidationDepth

Could you please explain to me what was happening?

bkoelman commented 2 weeks ago

I've never been able to reproduce it, so a minimal sample would help greatly. Perhaps we can fix it. Either way, let's leave this open as a reminder to add it to the Common Pitfalls documentation.

bkoelman commented 1 week ago

@alnotas Tried to reproduce the issue again this week, but I'm still unable to. I'd really like to get to the bottom of this. Is there anything you'd be able to provide? Are you using any third-party libraries? Can you share your full Program.cs?