[FromBody] Deserialization fails on ODataController when Body contains [NotMapped] property
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 505
- Forks
- 186
- PR merge metrics
- No merged PRs in 30d
Description
I am having issues with deserialization on my OData controller when using [FromBody] attribute when the body contains a property that doesn't exist in the model, such as an [NotMapped] property. Is there a way to tell the InputFormatter to ignore properties that don't exist in the model, instead of failing to bind the model giving me a null model? Here is an example model:
`public class Person
{
public Person() { }
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[NotMapped]
public string FullName => FirstName + " " + LastName;
}`
Note the [NotMapped] property FullName. I don't want this in my database, since it is just a simple calculated field, but I still want it to be serialized and deserialized in my ODataControllers. In order to have it serialized, I added the following to my GetEDMModel() function.
builder.StructuralTypes.First(t => t.ClrType == typeof(Attorney)).AddProperty(typeof(Person).GetProperty("FullName"));
This serializes the FullName property in the GET methods of my Person ODataController.
I have a React Client which receives this Person and manipulates it as necessary, and then makes a PUT request to the Person ODataController to update the Person. The body of the PUT request includes the [NotMapped] FullName property which does not have setter in the model.
Example body:
{
"@odata.context": "https://localhost:44304/rest/$metadata#Persons/$entity",
"Id": 1,
"FirstName": "Jimmy",
"LastName": "Johnson",
"FullName": "Jimmy Johnson",
}
The expected behavior (in my opinion) should be that the InputFormatter ignores the FullName property, since it is [NotMapped]in the model. Instead, theInputFormatterfails to bind the model, and thePerson` entity is null once inside my contoller.
`[ODataRoute("{id}")]
public async Task Put([FromODataUri] int id, [FromBody] Person person)
{
if (!ModelState.IsValid) return BadRequest(ModelState);
if (id != person.Id) return BadRequest();
db.Entry(person).State = EntityState.Modified;
await db.SaveChangesAsync();
return Updated(person);
}`
How do I get the inputformatter to deserialize an entity, even if the body includes a [NotMapped] property?
As a temporary work around, I am removing the [NotMapped] property on the client before the PUT request, but ideally this would be handled when deserializing.
I noticed the @odata.context property is automatically ignored, and does not cause deserialization to fail. Maybe there is a way to denote [NotMapped] to be ignored in a similar way?
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the OData InputFormatter path used by the [FromBody] Person parameter in Put, and review the custom GetEDMModel configuration that adds FullName. Reproduce the PUT request containing FullName and compare its handling with @odata.context. Done means the entity binds successfully, FullName is ignored for persistence, and ModelState remains valid.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100