Passing A List Of Objects Into An MVC Controller Method Using jQuery Ajax

C#asp.net MvcJquery

C# Problem Overview


I'm trying to pass an array of objects into an MVC controller method using jQuery's ajax() function. When I get into the PassThing() C# controller method, the argument "things" is null. I've tried this using a type of List for the argument, but that doesn't work either. What am I doing wrong?

<script type="text/javascript">
	$(document).ready(function () {
		var things = [
			{ id: 1, color: 'yellow' },
			{ id: 2, color: 'blue' },
			{ id: 3, color: 'red' }
		];

		$.ajax({
			contentType: 'application/json; charset=utf-8',
			dataType: 'json',
			type: 'POST',
			url: '/Xhr/ThingController/PassThing',
			data: JSON.stringify(things)
		});
	});
</script>

public class ThingController : Controller
{
	public void PassThing(Thing[] things)
	{
		// do stuff with things here...
	}

	public class Thing
	{
		public int id { get; set; }
		public string color { get; set; }
	}
}

C# Solutions


Solution 1 - C#

Using NickW's suggestion, I was able to get this working using things = JSON.stringify({ 'things': things }); Here is the complete code.

$(document).ready(function () {
	var things = [
		{ id: 1, color: 'yellow' },
		{ id: 2, color: 'blue' },
		{ id: 3, color: 'red' }
	];		
	
	things = JSON.stringify({ 'things': things });

	$.ajax({
		contentType: 'application/json; charset=utf-8',
		dataType: 'json',
		type: 'POST',
		url: '/Home/PassThings',
		data: things,
		success: function () { 			
			$('#result').html('"PassThings()" successfully called.');
		},
		failure: function (response) {			
			$('#result').html(response);
		}
	});	
});


public void PassThings(List<Thing> things)
{
	var t = things;
}

public class Thing
{
	public int Id { get; set; }
	public string Color { get; set; }
}

There are two things I learned from this:

  1. The contentType and dataType settings are absolutely necessary in the ajax() function. It won't work if they are missing. I found this out after much trial and error.

  2. To pass in an array of objects to an MVC controller method, simply use the JSON.stringify({ 'things': things }) format.

I hope this helps someone else!

Solution 2 - C#

Couldn't you just do this?

var things = [
    { id: 1, color: 'yellow' },
    { id: 2, color: 'blue' },
    { id: 3, color: 'red' }
];
$.post('@Url.Action("PassThings")', { things: things },
   function () {
        $('#result').html('"PassThings()" successfully called.');
   });

...and mark your action with

[HttpPost]
public void PassThings(IEnumerable<Thing> things)
{
    // do stuff with things here...
}

Solution 3 - C#

I am using a .Net Core 2.1 Web Application and could not get a single answer here to work. I either got a blank parameter (if the method was called at all) or a 500 server error. I started playing with every possible combination of answers and finally got a working result.

In my case the solution was as follows:

Script - stringify the original array (without using a named property)

    $.ajax({
        type: 'POST',
        contentType: 'application/json; charset=utf-8',
        url: mycontrolleraction,
        data: JSON.stringify(things)
    });

And in the controller method, use [FromBody]

    [HttpPost]
    public IActionResult NewBranch([FromBody]IEnumerable<Thing> things)
    {
        return Ok();
    }

Failures include:

  • Naming the content

    data: { content: nodes }, // Server error 500

  • Not having the contentType = Server error 500

Notes

  • dataType is not needed, despite what some answers say, as that is used for the response decoding (so not relevant to the request examples here).
  • List<Thing> also works in the controller method

Solution 4 - C#

Formatting your data that may be the problem. Try either of these:

data: '{ "things":' + JSON.stringify(things) + '}',

Or (from https://stackoverflow.com/questions/309115/how-can-i-post-an-array-of-string-to-asp-net-mvc-controller-without-a-form)

var postData = { things: things };
...
data = postData

Solution 5 - C#

I have perfect answer for all this : I tried so many solution not able to get finally myself able to manage , please find detail answer below:

       $.ajax({
            traditional: true,
            url: "/Conroller/MethodTest",
            type: "POST",
            contentType: "application/json; charset=utf-8",
            data:JSON.stringify( 
               [
                { id: 1, color: 'yellow' },
                { id: 2, color: 'blue' },
                { id: 3, color: 'red' }
                ]),
            success: function (data) {
                $scope.DisplayError(data.requestStatus);
            }
        });

Controler

public class Thing
{
    public int id { get; set; }
    public string color { get; set; }
}
 
public JsonResult MethodTest(IEnumerable<Thing> datav)
    {
   //now  datav is having all your values
  }

Solution 6 - C#

The only way I could get this to work is to pass the JSON as a string and then deserialise it using JavaScriptSerializer.Deserialize<T>(string input), which is pretty strange if that's the default deserializer for MVC 4.

My model has nested lists of objects and the best I could get using JSON data is the uppermost list to have the correct number of items in it, but all the fields in the items were null.

This kind of thing should not be so hard.

    $.ajax({
        type: 'POST',
        url: '/Agri/Map/SaveSelfValuation',
        data: { json: JSON.stringify(model) },
        dataType: 'text',
        success: function (data) {

    [HttpPost]
    public JsonResult DoSomething(string json)
    {
        var model = new JavaScriptSerializer().Deserialize<Valuation>(json);

Solution 7 - C#

This is working code for your query,you can use it.

Controler

    [HttpPost]
    public ActionResult save(List<ListName> listObject)
    {
    //operation return
    Json(new { istObject }, JsonRequestBehavior.AllowGet); }
    }

javascript

  $("#btnSubmit").click(function () {
    var myColumnDefs = [];
    $('input[type=checkbox]').each(function () {
        if (this.checked) {
            myColumnDefs.push({ 'Status': true, 'ID': $(this).data('id') })
        } else {
            myColumnDefs.push({ 'Status': false, 'ID': $(this).data('id') })
        }
    });
   var data1 = { 'listObject': myColumnDefs};
   var data = JSON.stringify(data1)
   $.ajax({
   type: 'post',
   url: '/Controller/action',
   data:data ,
   contentType: 'application/json; charset=utf-8',
   success: function (response) {
    //do your actions
   },
   error: function (response) {
    alert("error occured");
   }
   });

Solution 8 - C#

This is how it works fine to me:

var things = [
    { id: 1, color: 'yellow' },
    { id: 2, color: 'blue' },
    { id: 3, color: 'red' }
];

$.ajax({
    ContentType: 'application/json; charset=utf-8',
    dataType: 'json',
    type: 'POST',
    url: '/Controller/action',
    data: { "things": things },
    success: function () {
        $('#result').html('"PassThings()" successfully called.');
    },
    error: function (response) {
        $('#result').html(response);
    }
});

With "ContentType" in capital "C".

Solution 9 - C#

I can confirm that on asp.net core 2.1, removing the content type made my ajax call work.

function PostData() {
    var answer = [];

    for (let i = 0; i < @questionCount; i++) {
        answer[i] = $(`#FeedbackAnswer${i}`).dxForm("instance").option("formData");
    }

    var answerList = { answers: answer }

    $.ajax({
        type: "POST",
        url: "/FeedbackUserAnswer/SubmitForm",
        data: answerList ,
        dataType: 'json',
        error: function (xhr, status, error) { },
        success: function (response) { }
    });
}
[HttpPost]
public IActionResult SubmitForm(List<Feedback_Question> answers)
{}

Solution 10 - C#

Wrapping your list of objects with another object containing a property that matches the name of the parameter which is expected by the MVC controller works. The important bit being the wrapper around the object list.

$(document).ready(function () {
    var employeeList = [
        { id: 1, name: 'Bob' },
        { id: 2, name: 'John' },
        { id: 3, name: 'Tom' }
    ];      

    var Employees = {
      EmployeeList: employeeList
    }

    $.ajax({
        dataType: 'json',
        type: 'POST',
        url: '/Employees/Process',
        data: Employees,
        success: function () {          
            $('#InfoPanel').html('It worked!');
        },
        failure: function (response) {          
            $('#InfoPanel').html(response);
        }
    }); 
});


public void Process(List<Employee> EmployeeList)
{
    var emps = EmployeeList;
}

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Solution 11 - C#

     var List = @Html.Raw(Json.Encode(Model));
$.ajax({
    type: 'post',
    url: '/Controller/action',
    data:JSON.stringify({ 'item': List}),
    contentType: 'application/json; charset=utf-8',
    success: function (response) {
        //do your actions
    },
    error: function (response) {
        alert("error occured");
    }
});

Solution 12 - C#

Removing contentType just worked for me in asp.net core 3.1

All other methods failed

Solution 13 - C#

If you are using ASP.NET Web API then you should just pass data: JSON.stringify(things).

And your controller should look something like this:

public class PassThingsController : ApiController
{
    public HttpResponseMessage Post(List<Thing> things)
    {
        // code
    }
}

Solution 14 - C#

Modification from @veeresh i

 var data=[
    
                        { id: 1, color: 'yellow' },
                        { id: 2, color: 'blue' },
                        { id: 3, color: 'red' }
                        ]; //parameter
        var para={};
        para.datav=data;   //datav from View
        
          
        $.ajax({
                    traditional: true,
                    url: "/Conroller/MethodTest",
                    type: "POST",
                    contentType: "application/json; charset=utf-8",
                    data:para,
                    success: function (data) {
                        $scope.DisplayError(data.requestStatus);
                    }
                });
    
In MVC



public class Thing
    {
        public int id { get; set; }
        public string color { get; set; }
    }
    
    public JsonResult MethodTest(IEnumerable<Thing> datav)
        {
       //now  datav is having all your values
      }

Solution 15 - C#

What I did when trying to send some data from several selected rows in DataTable to MVC action:

HTML At the beginning of a page:

@Html.AntiForgeryToken()

(just a row is shown, bind from model):

 @foreach (var item in Model.ListOrderLines)
                {
                    <tr data-orderid="@item.OrderId" data-orderlineid="@item.OrderLineId" data-iscustom="@item.IsCustom">
                        <td>@item.OrderId</td>
                        <td>@item.OrderDate</td>
                        <td>@item.RequestedDeliveryDate</td>
                        <td>@item.ProductName</td>
                        <td>@item.Ident</td>
                        <td>@item.CompanyName</td>
                        <td>@item.DepartmentName</td>
                        <td>@item.ProdAlias</td>
                        <td>@item.ProducerName</td>
                        <td>@item.ProductionInfo</td>
                    </tr>
                }

Button which starts the JavaScript function:

 <button class="btn waves-effect waves-light btn-success" onclick="ProcessMultipleRows();">Start</button>

JavaScript function:

  function ProcessMultipleRows() {
            if ($(".dataTables_scrollBody>tr.selected").length > 0) {
                var list = [];
                $(".dataTables_scrollBody>tr.selected").each(function (e) {
                    var element = $(this);
                    var orderid = element.data("orderid");
                    var iscustom = element.data("iscustom");
                    var orderlineid = element.data("orderlineid");
                    var folderPath = "";
                    var fileName = "";
              
                    list.push({ orderId: orderid, isCustomOrderLine: iscustom, orderLineId: orderlineid, folderPath: folderPath, fileName : fileName});
                });
            
                $.ajax({
                    url: '@Url.Action("StartWorkflow","OrderLines")',
                    type: "post", //<------------- this is important
                    data: { model: list }, //<------------- this is important
                    beforeSend: function (xhr) {//<--- This is important
                      xhr.setRequestHeader("RequestVerificationToken",
                      $('input:hidden[name="__RequestVerificationToken"]').val());
                      showPreloader();
                    },
                    success: function (data) {
                    
                    },
                    error: function (XMLHttpRequest, textStatus, errorThrown) {
                    
                    },
                     complete: function () {
                         hidePreloader();
                    }
                });
            }
        }

MVC action:

[HttpPost]
[ValidateAntiForgeryToken] //<--- This is important
public async Task<IActionResult> StartWorkflow(IEnumerable<WorkflowModel> model)

And MODEL in C#:

public class WorkflowModel
 {
        public int OrderId { get; set; }
        public int OrderLineId { get; set; }
        public bool IsCustomOrderLine { get; set; }
        public string FolderPath { get; set; }
        public string FileName { get; set; }
 }

CONCLUSION:

The reason for ERROR:

"Failed to load resource: the server responded with a status of 400 (Bad Request)"

Is attribute: [ValidateAntiForgeryToken] for the MVC action StartWorkflow

Solution in Ajax call:

  beforeSend: function (xhr) {//<--- This is important
                      xhr.setRequestHeader("RequestVerificationToken",
                      $('input:hidden[name="__RequestVerificationToken"]').val());
                    },

To send List of objects you need to form data like in example (populating list object) and:

data: { model: list },

type: "post",

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHalcyonView Question on Stackoverflow
Solution 1 - C#HalcyonView Answer on Stackoverflow
Solution 2 - C#lanternmarshView Answer on Stackoverflow
Solution 3 - C#Gone CodingView Answer on Stackoverflow
Solution 4 - C#nick_wView Answer on Stackoverflow
Solution 5 - C#Veera InduvasiView Answer on Stackoverflow
Solution 6 - C#more urgent jestView Answer on Stackoverflow
Solution 7 - C#sach4allView Answer on Stackoverflow
Solution 8 - C#MyxomatosisView Answer on Stackoverflow
Solution 9 - C#MrSpyretosView Answer on Stackoverflow
Solution 10 - C#HoodlumView Answer on Stackoverflow
Solution 11 - C#Athul NalupurakkalView Answer on Stackoverflow
Solution 12 - C#Basharat HussainView Answer on Stackoverflow
Solution 13 - C#FleGManView Answer on Stackoverflow
Solution 14 - C#Minhajul IslamView Answer on Stackoverflow
Solution 15 - C#tickyView Answer on Stackoverflow