skip to Main Content

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.

2

Answers


  1. You can use JObject from NuGetpackage and use namespace "Newtonsoft.Json.Linq", but still you may want to use [FromBody] Attribute:

    public IActionResult AddPerson([FromBody] JObject objRequest)
    {
        Person person = JsonConvert.DeserializeObject<Person>(objRequest.ToString());
        string phone = objRequest.Value<string>("phone");  // additional field extraction
        // you can add any other fields to objRequest (Request Body) and only those matching fields will be automatically bind to Person object
        return Ok();
    }
    
    Login or Signup to reply.
  2. 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:

    public class PersonRequest
    {
       public Person Person { get; set; }
       public bool AdditionalParam { get; set; }
     }
    
    [HttpPost]
        public IActionResult AddPerson([FromBody] PersonRequest request)
        {
            // Your code
            return Ok();
        }
    

    Your JavaScript code need to adjust to send this composite object:

    var requestData = {
            person: person,
            additionalParam: true // additional parameter
        };
    
    $.ajax({
         url: '@Url.Action("AddPerson")', 
         contentType: 'application/json; charset=utf-8',
         data: JSON.stringify(requestData),
         type: 'POST',
         success: function (data) {
              // success
          }
        });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search