Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ajax json to MVC5 controller: Passing object containing a collection

Folks, I've attempted this on MVC4 and MVC5.

I need to pass an object with a few properties and a collection from the client to the controller.

I've defined the model in C# as:

public enum RequestMode { ReadOnly = 0, Edit = 1}

public class DataRequest
{
    public int ProjectId { get; set; }
    public RequestMode Mode { get; set; }
    public List<PageRequest> PageRequests { get; set; }

    public DataRequest()
    {
        PageRequests = new List<PageRequest>();
    }
}

public class PageRequest
{
    public int Id { get; set; }
    public int PageCurrent { get; set; }
    public int RowCountPerPage { get; set; }
}

The MVC Controller is defined as (just using it to set a breakpoint to check the request values):

[HttpPost]
public JsonResult Test(DataRequest request)
{
    return new JsonResult();
}

The Index.cshtml client contains the ajax call:

<script type="text/javascript">
    var RequestMode = { ReadOnly: 0, Edit: 1 };

    var dataRequest = { ProjectId: 17, Mode: RequestMode.Edit, PageRequests: new Array() };
    var pageRequest = { TableId: 3165, PageCurrent: 4, RowCountPerPage: 30 };
    dataRequest.PageRequests.push(pageRequest);

    $(document).ready(function () {
        $.ajax({
            data: dataRequest,
            type: 'POST',
            cache: false,
            url: '/Home/Test',
            success: function (data) {
            },
            fail: function (data) {

            }
        });

    });

</script>

I start debugging, the page loads and my breakpoint in the controller Test method gets hit.

In the debugger, the request object shows up as: Mode: Edit PageRequests: Count = 1 ProjectId: 17

When I expand the PageRequests collection property, I see: {Mvc5WebTest.Controllers.PageRequest} Id: 0 PageCurrent: 0 RowsPerPage: 0

I would expect the PageRequest object to be populated with the values I've set (i.e. 3165, 4, 30)

Using Fiddler, I see that the complete DataRequest object is getting turned into Json correctly, but it seems that the MVC controller can't turn it back into the C# object.

As a workaround, I can modify the ajax call on the client to var cdr = JSON.stringify(dataRequest);

$.ajax({
    dataType: 'json',
    type: 'GET',
    data: { jsonRequest: cdr },
    ...

And then in the controller

[HttpGet]
public ActionResult Test(string jsonRequest)
{
    var request = JsonConvert.DeserializeObject<DataRequest>(jsonRequest);
    return new JsonResult();
}

This works, but I'd rather not pass the data as a string.

Can anyone shed some light as to what is going on and what I need to do to get the collection populated?

like image 508
Arjay H. Avatar asked Mar 20 '14 17:03

Arjay H.


1 Answers

Because you're posting JSON data, you have to convert the object to string by using JSON.stringify and declare the contentType: "application/json; charset=utf-8"

$(document).ready(function () {
    $.ajax({
        data: JSON.stringify(dataRequest),
        type: 'POST',
        contentType: "application/json; charset=utf-8",
        url: '/Home/Test',
        success: function (data) {
        },
        fail: function (data) {

        }
});

I also noticed that in C# code, you defined PageRequest as

public class PageRequest
{
    public int Id { get; set; }
    public int PageCurrent { get; set; }
    public int RowCountPerPage { get; set; }
}

While in js,

var pageRequest = { TableId: 3165, PageCurrent: 4, RowCountPerPage: 30 };

There is a conflict between Id in C# and TableId in js. You will have to use one or the other.

like image 133
vbn Avatar answered Oct 06 '22 13:10

vbn