0

Array of objects after stringifying is not passed to controller action and the parameter of action (the model) is null.

I have tried many solutions given to this problem in StackOverflow but none of these solution solved my problem. I provided the links which I tried:

Pass array to mvc Action via AJAX

pass array in javascript object to mvc controller

Here is my code

JavaScript Code

$("#FormSubmit").click(function () {
    var datalist = [];

    $("#MarksTable tbody tr").each(function () {

        var obj = {};
        obj.StudentID = 1;
        obj.ExamTimeTableID = 1;
        obj.ClassActivity = $(this).find("td:eq(5) input").val();
        obj.IsPresent = $(this).find("td:eq(7) input").val();
        obj.Assignment = $(this).find("td:eq(6) input").val();
        obj.MidTerm = $(this).find("td:eq(3) input").val();
        obj.Final = $(this).find("td:eq(4) input").val();

        datalist.push(obj);
    });

    $.ajax({
        url: "@Url.Action("InsertData", "Examination")",
        type: "POST",
        cache: false,
        contentType: "application/json;charset=utf-8",
        dataType: "json",
        data: JSON.stringify(datalist),
        success: function (result) {
            alert(result);
        },
        error: function (errormessage) {
            alert(errormessage.responseText);
        }
    });
});

Action of Controller:

[HttpPost]
public JsonResult InsertData([FromBody] List<StudentMarksList> obj)
{

    DynamicParameters param = new DynamicParameters();
    .
    .
    .
    return Json(param.Get<string>("msg"));
}

The Model:

public class StudentMarksList
{
    public int StudentID { get; set; }
    public int ExamTimeTableID { get; set; }
    public int ClassActivity { get; set; }
    public int IsPresent { get; set; }
    public int Assignment { get; set; }
    public int MidTerm { get; set; }
    public int Final { get; set; }
}

Request Payload:

[,…]
0: {StudentID: 1, ExamTimeTableID: 1, ClassActivity: 3, IsPresent: 0, Assignment: 2, MidTerm: 5, Final: 4}
Assignment: 2
ClassActivity: 3
ExamTimeTableID: 1
Final: 4
IsPresent: 0
MidTerm: 5
StudentID: 1

Request Payload source:

[{"StudentID":1,"ExamTimeTableID":1,"ClassActivity":3,"IsPresent":0,"Assignment":2,"MidTerm":5,"Final":4}]

The obj should contains the passed objects but it is null.

Any Help???

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

4 Answers4

1

[Edit] Change the js as below:

    function toInt(str){
        var i = parseInt(str);
        return i ? i : 0;
    }

    $("#MarksTable tbody tr").each(function () {

        var obj = {};
        obj.StudentID = 1;
        obj.ExamTimeTableID = 1;
        obj.ClassActivity = toInt( $(this).find("td:eq(5) input").val());
        obj.IsPresent =toInt(  $(this).find("td:eq(7) input").val());
        obj.Assignment = toInt( $(this).find("td:eq(6) input").val());
        obj.MidTerm =toInt(  $(this).find("td:eq(3) input").val());
        obj.Final = toInt( $(this).find("td:eq(4) input").val());

        datalist.push(obj);
    });

This will make sure the empty input to 0 instead of null.


That's because on your server side you're declaring the ClassActivity/ClassActivity/Assignment/... as int type but your js send all them as string. For example, the Payload sent to server will be something like:

[{"StudentID":1,"ExamTimeTableID":1,"ClassActivity":"3","Assignment":"aa","MidTerm":"333333333","Final":"3333"},{"StudentID":1,"ExamTimeTableID":1,"ClassActivity":"","Assignment":"s","MidTerm":"2","Final":"1"},{"StudentID":1,"ExamTimeTableID":1,"ClassActivity":"3","Assignment":"","MidTerm":"2","Final":"1"}]

Please either change the property type or convert the $(this).find("td:eq(7) input").val() result (a string) to int/bool/... type before sending them.

itminus
  • 23,772
  • 2
  • 53
  • 88
  • I send a single object manually with string value to `ClassActivity` and others which will be numbers it works. the value of these fields are numbers – Asrar Ahmad Ehsan Oct 31 '19 at 09:00
  • @AsrarAhmadEhsan Could you please press `F12` and inspect the `Network` and show us the real payload sent to the server ? – itminus Oct 31 '19 at 10:58
  • @AsrarAhmadEhsan I copy & paste your code and create a new project using ASP.NET Core `2.2.402`, but the payload ```[{"StudentID":1,"ExamTimeTableID":1,"ClassActivity":3,"IsPresent":0,"Assignment":2,"MidTerm":5,"Final":4}]``` works for me. Is there a way/project online that reproduces the same issue ? – itminus Oct 31 '19 at 11:21
1

Simply add this property to your ajax call:

traditional:true,

such that your ajax call looks like this at the end

$.ajax({
    url: "@Url.Action("InsertData", "Examination")",
    type: "POST",
    cache: false,
    traditional:true,
    contentType: "application/json;charset=utf-8",
    dataType: "json",
    data: JSON.stringify(datalist),
    success: function (result) {
        alert(result);
    },
    error: function (errormessage) {
        alert(errormessage.responseText);
    }
});

Happy coding. Hope it helps someone just as it helped me.

Chidi-Nwaneto
  • 634
  • 7
  • 11
0

You can try this also.

cshtml page you need to add one form tag like eg.

<div style="display:none;">
<form id="FormPost"></form>
</div>

Jquery Code

$("#FormSubmit").click(function () {

    $("#FormPost").html('');
    $("#MarksTable tbody tr").each(function (index,elem) {

       addHidden("StudentID["+index+"]","1");
       addHidden("ExamTimeTableID["+index+"]","1");
       addHidden("ClassActivity["+index+"]",$(this).find("td:eq(5) input").val());
       addHidden("IsPresent["+index+"]",$(this).find("td:eq(7) input").val());
       addHidden("Assignment["+index+"]",$(this).find("td:eq(6) input").val());
       addHidden("MidTerm["+index+"]",$(this).find("td:eq(3) input").val());
       addHidden("Final["+index+"]",$(this).find("td:eq(4) input").val());
    });

    $.ajax({
        url: "@Url.Action("InsertData", "Examination")",
        type: "POST",
        cache: false,
        contentType: "application/json;charset=utf-8",
        dataType: "json",
        data: $("#FormPost").serialize(),
        success: function (result) {
            alert(result);
        },
        error: function (errormessage) {
            alert(errormessage.responseText);
        }
    });
});

function addHidden(key, value) {   
    var input = document.createElement('input');
    input.type = 'hidden';
    input.name = key;
    input.value = value;
    $("#FormPost").appendChild(input);
}

Action of Controller:

[HttpPost]
public JsonResult InsertData(List<StudentMarksList> obj)
{

    DynamicParameters param = new DynamicParameters();
    .
    .
    .
    return Json(param.Get<string>("msg"));
}

jishan siddique
  • 1,848
  • 2
  • 12
  • 23
0

That could be dynamic value of one of property in object below is not a number, it contains some alphabet characters.

var obj = {};
        obj.StudentID = 1;
        obj.ExamTimeTableID = 1;
        obj.ClassActivity = $(this).find("td:eq(5) input").val();//this value could be not a number, ex: 'abc' text
        obj.IsPresent = $(this).find("td:eq(7) input").val();
        obj.Assignment = $(this).find("td:eq(6) input").val();
        obj.MidTerm = $(this).find("td:eq(3) input").val();
        obj.Final = $(this).find("td:eq(4) input").val();

It will be reason that Asp.Net cannot deserialize your action parameter item to object of StudentMarksList.

If above is not the root cause, you can follow this question to log out serialization errors to have further investigation.