MRP
MRP

Reputation: 619

Custom ASP.Net Core JSON model binder

My posted JSON object is this:

{{
 "emails": [
        {
          "To": "[email protected]",
          "Subject": "Subject",
          "Body": "Body",
          "ID": "d3d13242-6eff-4c57-b718-ef5ad49fe301"
        },
        {
          "To": "[email protected]",
          "Subject": "Subject",
          "Body": "Body",
          "ID": "101edaf0-fcb4-48fc-9e9e-0d7492b591b0"
        }
      ]
}}

By default ASP.NET model binder will not bind this JSON object and as you can see here I get always null when I send post request to the API:

[HttpPost, Route("Send")]
public async Task<IActionResult> Send(Email[] emails)
{
  var toSave = from email in emails
                         select new EmailQueueItem
                         {
                             Html = true,
                             To = email.To,
                             Subject = email.Subject,
                             Body = email.Body
                         };

   await Database.BulkInsert(toSave.ToArray());

   return Ok();
 }

emails property is always null. I would appreciate any help for creating custom model binder that handel this kind of JSON objects.

Upvotes: 0

Views: 1430

Answers (1)

Marcus H&#246;glund
Marcus H&#246;glund

Reputation: 16856

The issue is that you are actually sending an object containing one property named emails, not an array, to the controller

Option one: The client object needs to contain just the array

 [
    {
      "To": "[email protected]",
      "Subject": "Subject",
      "Body": "Body",
      "ID": "d3d13242-6eff-4c57-b718-ef5ad49fe301"
    },
    {
      "To": "[email protected]",
      "Subject": "Subject",
      "Body": "Body",
      "ID": "101edaf0-fcb4-48fc-9e9e-0d7492b591b0"
    }
  ]

Then read the array from the request body

public async Task<IActionResult> Send([FromBody]Email[] emails)

Option 2: When you define the array like this in the client

{
  "emails":...
}

You need to match that object setup on the controller by defining a model which contains a property called emails

public class RequestModel
{
    public Email[] emails { get; set; }
}

Then in the controller method, use the model and read it from the body

public async Task<IActionResult> Send([FromBody]RequestModel emails)

Upvotes: 1

Related Questions