Igor
Igor

Reputation: 354

ASP.NET Core Razor ajax POST request data object is empty

There is a simple ajax POST request that must stringify a simple class and pass it in the body of POST request, but the Person parameter on the server-side has empty(default) values

// javascript
var person = { "FirstName": "Andrew", "LastName": "Lock", "Age": "31" };
$.ajax({
    type: "POST",
    url: "/UpdatePostBody?handler=Abc",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    data: JSON.stringify(person),
    headers: {
        RequestVerificationToken:
            $('input:hidden[name="__RequestVerificationToken"]').val()
    },
})
    .done(function (result) {
        console.log(result);
});
// C# code
public IActionResult OnPostAbc(Person person)
{
    return new JsonResult("my result");
}

enter image description here

On the server-side, there is a simple ASP.NET Core Razor page with a method that gets hit and returns the result but the person param members have no values.

Upvotes: 3

Views: 9760

Answers (3)

Mike Brind
Mike Brind

Reputation: 30110

As you have identified, JSON is sent as part of the request body. You could (as you have done in your own answer) read the input stream and deserialize it manually, but there is a much simpler way using the [FromBody] attribute on the handler parameter:

public IActionResult OnPostAbc([FromBody] Person person)
{
    return new JsonResult($"my result: {person.FirstName} {person.LastName}");
}

However, this only works in 3.1 with the default serializer (System.Text.Json) if you remove the quotes from numbers in your person object:

var person = { "FirstName": "Andrew", "LastName": "Lock", "Age": 31 };

Or if you add your own type converter.

The previous serializer, JSON.Net, is happy with either version. And quoted numbers are supported in ASP.NET Core 5.

Upvotes: 2

Yiyi You
Yiyi You

Reputation: 18189

Your Pesron data is null is because your Age in class Person is int type.And your person in { "FirstName": "Andrew", "LastName": "Lock", "Age": "31" } is string type,So you cannot get it.Also,as you pass json data from ajax to handler,you need to add [FromBody] in handler.Here is a demo:

cshtml:

<button onclick="postdata()">Abc</button>
function postdata() {
        //change Age type to int
        var person = { "FirstName": "Andrew", "LastName": "Lock", "Age": 31 };
        $.ajax({
            type: "POST",
            url: "/UpdatePostBody?handler=Abc",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: JSON.stringify(person),
            headers: {
                RequestVerificationToken:
                    $('input:hidden[name="__RequestVerificationToken"]').val()
            },
        })
            .done(function (result) {
                console.log(result);
            });
    }

cshtml.cs:

public IActionResult OnPostAbc([FromBody]Person person)
        {
            return new JsonResult("my result");
        }

result: enter image description here

Upvotes: 10

Igor
Igor

Reputation: 354

Solved by reading the data from POST body

public async Task<IActionResult> OnPostAbc()
{
    var buffer = new byte[1024];
    using (var ms = new MemoryStream())
    {
        var read = 0;
        while ((read = await Request.Body.ReadAsync(buffer, 0, buffer.Length)) != 0)
        {
            ms.Write(buffer, 0, read);
        }
        ms.Seek(0, SeekOrigin.Begin);
        var person = 
            JsonConvert.DeserializeObject<Person>(Encoding.UTF8.GetString(ms.GetBuffer()));
        return new JsonResult($"my result: {person.FirstName} {person.LastName}");
    }
}

Upvotes: 1

Related Questions