I have the following JS code:
const data = await fetch("/api/database/sample",
{
method: "post",
headers: { "Content-Type": "application/json; charset=UTF-8" },
body: JSON.stringify({ names: ['ahmad', 'mutawa'], age: 22 })
});
This code successfully triggers the following method in a Mvc Controller (in a .net core 8 application):
[Route("api/[controller]")]
public class DatabaseController: Controller
{
[HttpPost("sample")]
public IActionResult Sample(string[] names, int age)
{
// names = [] // why ????
// age = 0
return Json(/* some object array */);
}
}
The only issue is, the parameters names
and age
are set to default 'empty or nullfor names, and
0for
age`.
I changed the Content-Type
to urlencoded-form
, and that allowed me to set the age successfully, but the names
array is treated as a single string variable, meaning all values within the array are inserted into the first element.
How do I resolve this issue?
If you don't want use dto to bind the data, you can change your backend code like below to fix the issue.
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
namespace WebApplication9.Controllers
{
[ApiController]
[Route("[controller]")]
public class DatabaseController : ControllerBase
{
[HttpPost("sample")]
public IActionResult Sample(Dictionary<string, object> payload)
{
// names = [] // why ????
// age = 0
var names = payload["names"] as JArray;
var age = Convert.ToInt32(payload["age"]);
return Ok(new { names, age });
}
}
}
Recommended Solution
Use FromBody attribute to bind the data.
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
namespace WebApplication9.Controllers
{
[ApiController]
[Route("[controller]")]
public class DatabaseController : ControllerBase
{
[HttpPost("sample")]
public IActionResult Sample([FromBody] SampleRequest request)
{
var names = request.Names;
var age = request.Age;
return Ok(names);
}
public class SampleRequest
{
public string[] Names { get; set; }
public int Age { get; set; }
}
}
}