mhsimkin
mhsimkin

Reputation: 321

Model Binding ignoring properties that have the JsonIgnore attribute

I'm building a web api microservice using Core 3. I have a class defined as follows:

public class UserSourceList
{
    [JsonIgnore]
    public string UserId { get; set; }

    [JsonIgnore]
    public string ListId { get; set; }

    public string Name { get; set; }

    [JsonConverter(typeof(StringEnumConverter))]
    public ListTypes ListType { get; set; }

    public List<string> Ids { get; set; }

    public DateTimeOffset CreationTime { get; set; }
}

When the framework attempts to bind the data provided by a HTTP PUT, it will not populate the UserId and ListId fields. As a result, model binding is failing during validation and returning a HTTP 400, stating that UserId and ListId are required.

The controller's action method is defined as follows:

 [HttpPut("{userId:userid}/{listId:listid}", Name = "ReplaceUserList")]
 public ActionResult Replace(string userId, string listId, UserSourceList model)
 {
    return Ok(_listManager.ReplaceUserList(model.UserId, model.ListId, model));
 }

A typical call to the API would look similar to this:

PUT /api/v1/listmgmt/abc123def456/c788f2f7b7984424910726d4a290be26

PUT Body

{
  "name": "Test",
  "listType": "Eans",
  "ids": ["97814571867716", "9781430257615", "9780982550670"],
  "userId":"abc123def456",
  "listId":"c788f2f7b7984424910726d4a290be26"
}

If I removed the JsonIgnore Attribute from the UserId and ListId properties of the model, everything binds as expected.

Is it expected behavior that model binding will ignore fields flagged with JsonIgnore?

I know I can work around it by changing how my validation code works or I can split my model. I would like to understand the current behavior as it is different from what I expected and experienced with ASP.NET MVC 4 and WebApi 2.

Thanks

Upvotes: 2

Views: 3347

Answers (2)

mhsimkin
mhsimkin

Reputation: 321

Short answer, Newtonsoft Json.Net is being used to deserialize the post/put body when the content type is application/json. Therefore, the userId and listId parameters are being ignored during deserialization, but evaluated during model validation.

I removed the JsonIgnore Attribute as well as all the Data Annotations, and changed to the FluentValidation package which provided the ability at runtime to configure how the body should be validated based up the type of call made.

Upvotes: 2

tiennsloit
tiennsloit

Reputation: 91

I think the reason is because of this:

[HttpPut("{userId:userid}/{listId:listid}", Name = "ReplaceUserList")]

userId and listId are required and cannot be ignored because they are defined in the annotation HttpPut. I think you need to remove them from HttpPut's parameters and find another way to get around this.

Hope this helps!

Upvotes: 0

Related Questions