No way to create a resource derived from Identifiable<string> without sending Id from client side
See original GitHub issueDESCRIPTION
Cannot make a client POST request to create a resource derived from Identifiable<string>
- Controller validates the model saying
The Id field is required.
For many reasons, we might want to assign the Id from the server-side. In the 4.x version, I assign an Id at OnWritingAsync
. However, with the 5.x version, we validate the ModelState before reaching the OnWritingAsync
function
STEPS TO REPRODUCE
public sealed class RgbColor : Identifiable<string>
{
[Attr]
public string DisplayName { get; set; } = null!;
[HasOne]
public WorkItemGroup? Group { get; set; }
}
options.AllowClientGeneratedIds = false;
options.ValidateModelState = true;
POST request with the request body
{
"data":{
"type":"rgbColor",
"attributes":{
"DisplayName":"Blue"
}
}
}
EXPECTED BEHAVIOR
- Allow assigning Id from server-side
- Don’t throw the Modal Validation with Id
ACTUAL BEHAVIOR
- The controller always validates the model and throws
The Id field is required.
exception
VERSIONS USED
- JsonApiDotNetCore version: 5.0.1
- ASP.NET Core version: 6.0
- Entity Framework Core version: 6.0
- Database provider: InMemory
Issue Analytics
- State:
- Created a year ago
- Comments:5 (4 by maintainers)
Top Results From Across the Web
rest - Can I PUT without an ID?
If a resource can be identified without an ID, i.e. there only ... No. PUT means "create or update", and should come with...
Read more >ModelState validation changes when adding a new ...
No way to create a resource derived from Identifiable<string> without sending Id from client side json-api-dotnet/JsonApiDotNetCore#1153.
Read more >To include a resource ID in the payload or to derive from URI
1. The reason for us questioning the placement of the ID in the payload was due to Backbone.js passing the ID in a...
Read more >What security issues could occur when generating ids on ...
The only way to ensure that a client side id does not conflict with existing ids is to check for this on the...
Read more >Adobe Sign for Microsoft PowerApps and Power Automate
Adobe Acrobat Sign can be integrated with Microsoft® Power Automate and the PowerApps environment to provide you with a smooth digital ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I’ve taken a deep dive and found the root cause.
Using a minimal repro project, I was unable to get the same validation error. So I started comparing the compiler-generated nullability attributes in the DLL using ILDASM and found interesting differences. The JsonApiDotNetCore.Annotations assembly contained
[NullableContextAttribute]
usages that weren’t in the DLL from my simplified repro project:As described here, this is because the
StringId
andLocalId
properties are missing in my simplified version ofIdentifiable
:There’s a bug in ASP.NET 6: it duplicates compiler logic to determine nullability, but takes some shortcuts and gets it wrong. This was recently fixed by replacing the custom logic with relying on the
NullabilityInfoContext
reflection API in the runtime. I’ve created a bug report here.But it doesn’t stop there. Turns out that
NullabilityInfoContext
in .NET 6 does not work correctly for our case (see the end of my bug report). There are several recent fixes to that, see https://github.com/dotnet/runtime/issues?q=is%3Aclosed+NullabilityInfoContext+label%3Aarea-System.Reflection.So I tried with .NET 7 preview 4, where everything works as expected. The solution I recommend to you: use option 3 from my earlier comment. When updating to .NET 7, you can remove the
Id
property override.Thanks for the extra details. One difference between v4 and v5 is that v5 is compiled with nullable reference types enabled. This changes how ASP.NET ModelState interprets the required-ness of
Identifiable.Id
.Yesterday I started digging into this some more, but unfortunately my time is limited. I’ll see if I can continue my investigation during the weekend. Depending on my observations, I’ll reopen this issue.