Search code examples
jqueryasp.netajaxasp.net-core-mvc.net-8.0

jQuery ajax post request on ASP.NET Core MVC with application/json


I'm trying to make and ajax call using jQuery.ajax and contentType: 'application/json; charset=utf-8'.

I created a new project for ASP.NET Core MVC with .NET 8.

This is the Javascript code:

$('#addPerson').click(function () {
    var person = {
        Name: 'Test1',
        Email: 'Test2'
    };

    $.ajax({
        url: '@Url.Action("AddPerson")',
        contentType: 'application/json; charset=utf-8',
        data: JSON.stringify({ person: person }),
        // data: { person: person },
        type: 'Post',
        success: function (data) {
            
        }
    });
});

Here is the controller method and the model:

[HttpPost]
public IActionResult AddPerson(Person person)
{
    return Ok();
}

public class Person
{
    public string Name { get; set; }
    public string Email { get; set; }
}

For some reason the person's properties are always null.

If I comment the lines shown below in the ajax call

contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ person: person }),

and uncomment the line shown below then I can see properties filled in the controller correctly.

// data: { person: person },

Also if I add [FromBody] in my controller parameter and change the data to JSON.stringify(person), it still works but I don't want that since in many cases I may need to send to controller a whole person object and then additional parameters.

In previous versions in ASP.NET MVC, I believe this was working. My guess is that I have to specify a serializer in program.cs to make it work. But I tried different variations without success.


Solution

  • When you specify contentType: 'application/json; charset=utf-8', you're telling the server that the data being sent in the request body is in JSON format. ASP.NET Core's default model binder expects the JSON data to match the parameter of the action method exactly if you're not using [FromBody].In ASP.NET Core, the [FromBody] attribute explicitly tells the model binder to look for data in the request body and try to bind it to the action method's parameter. Without [FromBody], model binding looks at various sources including the query string and form data, but it has specific expectations about the request body that often require [FromBody] for JSON data.Your AJAX call is sending data in a nested object format: { person: person }. However, your action method expects a flat Person object. This is the reaosn why your properties are coming across as null when you use JSON.stringify({ person: person }) without [FromBody].

    You could try this below code to resolve the issue:

     $('#addPerson').click(function () {
        var person = {
            Name: 'Test1',
            Email: 'Test2'
        };
    
        $.ajax({
            url: '@Url.Action("AddPerson")' + '?additionalParam=true', //additional parameters
            contentType: 'application/json; charset=utf-8',
            data: JSON.stringify(person), // Send person object directly
            type: 'POST',
            success: function (data) {
                // success
            }
        });
    });
    

    Controller:

    [HttpPost]
    public IActionResult AddPerson([FromBody] Person person, [FromQuery] bool additionalParam)
    {
        // Your Code
        return Ok();
    }
    

    You need to use [FromBody] to bind the JSON body to your model