I am using .NET Core and I am attempting to send an array from the .cshtml page via Ajax to the corresponding method. I have a strongly typed class that I wish the array to bind to but when the method is called, it returns null. I have managed to send simple data back (e.g. a single string) but anything like an array and it returns null.
This is the Ajax call and the array I am trying to send through.
var miniPediPrice = document.getElementById("MiniPedi").value * 1500;
var miniPediDuration = parseFloat('#Model.miniPedi.Duration');
const products = [{
Name: '#Model.miniPedi.Name',
Price: miniPediPrice.toString(),
Duration: miniPediDuration.toString(),
GelPolish: "false",
NailArt: "false"
}]
console.log(products);
const total = 0;
try {
$.ajax({
dataType: 'json',
type: 'POST',
url: "/Products?handler=CalculatePrice",
traditional: true,
data: JSON.stringify(products),
//data: JSON.stringify({ products: products }),
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
success: function (data) {
console.log(data);
$("#totalPrice").val(data)
},
});
} catch (e) {
}
The method that the ajax calls. The "products" is always null.
public IActionResult OnPostCalculatePrice([FromBody] List<Products> products)
{
var totalPrice = "";// product.Name;
//TotalPrice = "£" + (totalPrice / 100).ToString();
return new JsonResult(totalPrice);
}
Model class for Products:
public class Products
{
public string Name { get; set; }
public decimal Price { get; set; }
public decimal Duration { get; set; }
public bool GelPolish { get; set; }
public bool NailArt { get; set; }
public Products(string productName, decimal productPrice, decimal productDuration, bool gelPolish, bool nailArt)
{
Name = productName;
Price = productPrice;
Duration = productDuration;
GelPolish = gelPolish;
NailArt = nailArt;
}
}
I have searched high and low for how to fix this but no luck. I am new to jQuery/Javascript so I am still learning syntax etc. I hope the information posted is enough.
You can do following steps to make it work.
1:Remove the constructor from your produst.
2:Change your ajax like(add contentType: "application/json" and decimal,bool type no need to convert to string):
var products =
[{
Name: "assad",
Price: 12.5,
Duration:4.5,
GelPolish: false,
NailArt: false
}];
$.ajax({
dataType: 'json',
contentType: "application/json",
type: 'POST',
url: "/Products?handler=CalculatePrice",
traditional: true,
data: JSON.stringify(products),
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
success: function (data) {
console.log(data);
$("#totalPrice").val(data)
},
});
3:Your action:
public IActionResult OnPostCalculatePrice([FromBody] List<Products> products)
{
var totalPrice = "";// product.Name;
//TotalPrice = "£" + (totalPrice / 100).ToString();
return new JsonResult(totalPrice);
}
Test result:
Can you
Add 'contentType':'application/json'; in your ajax call.
Don't do JSON.stringfy.Directly use the products in data.
Remove the constructor from Products.cs class (It should be Product
sinceyou are passing the array list to denote products)
Assign Price,duration decimal value and GelPoslish, NailArt boolean value (boolean without quotes.)
.
The Json I wish to pass into an MVC 5 controller is as follows:
var searchInputs = { "Id": [ "1", "2" ] };
As you can see, It is just an array of strings called Id.
I have created a class which should receive this array.
public class SearchList
{
public SearchList()
{
Id = new List<string>();
}
public List<string> Id { get; set; }
}
The controller is defined as:
[HttpPost]
public FilePathResult DownloadSelectedPDF(SearchList data)
{
...
}
No errors are thrown, but the controller does not get the data, but returns a zero collection.
As per request, I have added the Ajax call.
$.ajax({
url: url,
method: 'POST',
dataType: "json",
data: data,
success: function (result) {
console.log();
if (result.Success) {
console.log("ajax: result successful");
if (result.SuccessMessage !== null)
showSuccess(result.SuccessMessage);
successCallBack(result.Data);
} else {
console.warn("ajax: result unsuccessful");
showError(result.ErrorMessage);
failCallBack(result.ErrorMessage);
}
},
error: function (jqXHR, textStatus, errorThrown) {
if (!supressWaitingPopup)
waitingModal(false);
console.warn("ajax error");
showError(errorThrown);
failCallBack(errorThrown);
}
});
Where the data is the searchInputs varaiable.
UPDATE:
The searchInput can have multiples so I should have defined it as:
var searchInputs = { "Id": [ "1", "2", ... ] };
FURTHER UPDATE:
I have used the ajax params suggested, both together and separately.
Using the same ajax call, if these params are present, then a call using this structure fails:
this.JsonData = {
"__RequestVerificationToken": $('input[name=__RequestVerificationToken]').val(),
"searchMode":
{
"mode": Number(mode.val()),
"pageSize": Number(pagesize.val()) || 5, //Initial Page Size Set Here
"pageNumber": Number(pagenumber.val()) || 1, //Start on page one
"sortField": sortfield.val() || "PODRef",
"sortDirection": sortdirection.val() || "desc"
},
"searchData":
{
"Compare": Number(StdComparison.val()),
"SearchTextFrom": searchText.val(),
"SearchTextTo": searchTextTo.val()
}
This is true if I JSON.stringify the data or not.
var obj = { pVar: val, pVar1: val1 };
$.ajax({
type: "POST",
url: '#Url.Action("DownloadSelectedPDF", "Controller")',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(obj),
dataType: 'json',
success: function (data) {
$("#divID").html(data.Html);
},
error: errorFunc
});
[HttpPost]
public FilePathResult DownloadSelectedPDF(string pVar, string pVar1)
{
return Json(new { Html = "someStuff")});
}
Ok, I have found a solution that enables my NOT to have to add the parameters of contentType or tradional to the ajax call.
var searchInputs = { "Id": [ "1", "2", ... ] };
This is an Array of string objects, so what I have done is changed it to:
var postData = { Id: _self.Array }
Then all that was needed was to change the parameter on the controller to
List<string> Id
Note: Parameter name matches the name given for the array
That's it. I know that this solution is not Json based, but it works and gets me out of a hole.
Many thanks to all that looked at this and special thanks to d.popov for this contribution:
how-can-i-post-an-array-of-string-to-asp-net-mvc-controller-without-a-form
Have you tried this?
[HttpPost]
public FilePathResult DownloadSelectedPDF([FromBody]SearchList data)
{
...
}
It would be worth adding this to your ajax call as well:
contentType: "application/json; charset=utf-8",
I use this in my controllers and I receive an initialized object (some properties are null if the sender does not include the "property": "value" pair).
I am not sure how it'll deal with List<string> though. If that property comes null maybe try changing it to string[] just to see if it works.
I have a test js function that should post data to webapi by Post method
function test() {
var puffs = [];
var puffObject = {
id: "2735943",
priority: "1"
};
puffs.push(puffObject);
puffs.push(puffObject);
var dto =
{
po: puffs
};
$.ajax({
type: "POST",
url: "../api/PuffPriority/",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(dto),
dataType: "json",
success: function (data, status) {
if (data) {
console.log("Welcome");
} else {
console.log("No data");
}
},
error: function (error) {
console.log("Error");
}
});
}
In the controller class i have
public void Post(PuffPriority[] po){
//Do something here with po, but po is always empty
}
where PuffPriority Model is
public class PuffPriority
{
public string id { get; set; }
public string priority { get; set; }
}
I dont know whats wrong , the values are sent by JS but api Controller don't fetch it :( Please help, i have already wasted a lot of time.
You have a bug in your code.
Simply change
url: "../api/PuffPriority/"
to
url: "../api/Post/"
or change your method name from Post to PuffPriority
Changed
public void Post(PuffPriority[] po){
//Do something here with po, but po is always empty
}
To
[FromBody]List<PuffPriority> po{
//Do something here with po, but po is always empty
}
I´m having difficulties matching Javascript Ajax to ASP.NET Controller type. All parameters comes fine, except for the MsgData that comes null when received by the Controller.
My Controller classes and code:
public class AjaxMessage
{
public enum MsgStatusType : int { OK, NOK }
public string MsgType { get; set; }
public List<AjaxMessageItem> MsgData { get; set; }
public MsgStatusType MsgStatus { get; set; }
public string MsgStatusMsg { get; set; }
}
And
public class AjaxMessageItem
{
public string Name { get; set; }
public string Value { get; set; }
public AjaxMessageItem()
{
Name = String.Empty;
Value = String.Empty;
}
}
Finally:
public ActionResult Get(AjaxMessage ajaxMessage)
{
... do some stuff...
}
My Javascript call:
var url = '#Url.Action("Get", "AjaxServer")';
$.ajax({
url: url,
cache: false,
type: "POST",
data: {
'MsgType': 'MsgType1',
'MsgData': { 'Name': 'customerId', 'Value': 'current' },
'MsgStatus': 'OK',
'MsgStatusMessage' : ''
},
success: function (data) {
if (data.msgStatus != 'OK') {
var errorMsg = 'Error reading data.' + data.msgStatusMessage;
alert(errorMsg);
return;
}
... do some stuff...
}
},
error: function (data) {
alert('Error retrieving Ajax data.');
}
});
At controller, I´m getting MsgType, MsgStatus and MsgStatusMsg fine whan looking for ajaxMessage variable, but MsgData is always null and shall be receiving the customerId data.
I need some help to solve that. Please help me to find out what´s missing... Thanks.
Because you're sending an array, you will have to convert the object to JSON explicitly using JSON.stringify, wrap the MsgData in [] and set contentType: 'application/json, charset=utf-8'
$.ajax({
url: url,
cache: false,
type: "POST",
contentType: 'application/json, charset=utf-8',
data: JSON.stringify({
'MsgType': 'MsgType1',
'MsgData': [{ 'Name': 'customerId', 'Value': 'current' }],
'MsgStatus': 'OK',
'MsgStatusMessage' : ''
}),
success: function (data) {
if (data.msgStatus != 'OK') {
var errorMsg = 'Error reading data.' + data.msgStatusMessage;
alert(errorMsg);
return;
}
... do some stuff...
}
},
error: function (data) {
alert('Error retrieving Ajax data.');
}
});
your data is sent to server, but you cant get that correctly, you can check the network tab of your browser, or check data has been sent to server by something like this:
HttpUtility.UrlDecode(Request.Form.ToString())
i think the easiest way is always stringify your data, and deserializing that to your poco object on server
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; }
}
}
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:
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.
To pass in an array of objects to an MVC controller method, simply use the JSON.stringify({ 'things': things }) format.
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...
}
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
Formatting your data that may be the problem. Try either of these:
data: '{ "things":' + JSON.stringify(things) + '}',
Or (from How can I post an array of string to ASP.NET MVC Controller without a form?)
var postData = { things: things };
...
data = postData
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
}
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);
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".
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");
}
});
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)
{}
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; }
}
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");
}
});
Removing contentType just worked for me in asp.net core 3.1
All other methods failed
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
}
}
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
}
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",
Nothing worked for me in asp.net core 3.1. Tried all the above approaches.
If nothing is working and someone is reading the rows from table
and wanted to pass it to Action method try below approach...
This will definitely work...
<script type="text/javascript">
$(document).ready(function () {
var data = new Array();
var things = {};
// make sure id and color properties match with model (Thing) properties
things.id = 1;
things.color = 'green';
data.push(things);
Try the same thing for dynamic data as well that is coming from table.
// var things = [ { id: 1, color: 'yellow' }, { id: 2, color: 'blue' }, { id: 3, color: 'red' } ];
$.ajax({
contentType: 'application/json;',
type: 'POST',
url: 'your url goes here',
data: JSON.stringify(things)
});
});
</script>
public class ThingController : Controller
{
public void PassThing([FromBody] List<Thing> things)
{
// do stuff with things here...
}
public class Thing
{
public int id { get; set; }
public string color { get; set; }
}
}
The way that worked for me
$.ajax({
url: '#Url.Action("saveVideoesCheckSheet", "checkSheets")',
type: "POST",
contentType: "application/x-www-form-urlencoded; charset=utf-8",
data: "data=" + JSON.stringify(videos),
success: function (response) {
window.location.reload(true);
},
failure: function (msg) {
}
});
});
Controller
public string saveVideoesCheckSheet(string data)
{
List<editvideo> lst = JsonConvert.DeserializeObject<List<editvideo>>(data);...}
After much experimentation, bit of a cheat.