I am trying to pass an array of json objects to my controller action and it keeps coming in as null.
Javascript Code
function UpdateSelected() {
var items = {};
//Loop through grid / sub grids and create json array
$('.k-detail-row .k-grid').each(function () {
var grid = $(this).data("kendoGrid");
var selectedElements = grid.select();
for (var j = 0; j < selectedElements.length; j++) {
var item = grid.dataItem(selectedElements[j]);
var json = item.toJSON();
items = [].concat(items, json);
}
})
//shift the first empty space out
items.shift();
//items is ready to send
alert(JSON.stringify(items));
$.ajax({
cache: false,
url: '/Update/GetSchematicsForSelectedVariants',
type: 'GET',
data: JSON.stringify(items),
success: function (data) {
alert("success");
}
});
}
The Json array looks like this:
Controller Action
public JsonResult GetSchematicsForSelectedVariants(List<VariantViewModel> vm)//vm coming in null
{
return Json(_dataAccessService.GetSchematicsForMacroVariants(vm),JsonRequestBehavior.AllowGet);
}
VariantViewModel
public class VariantViewModel
{
public string Id { get; set; }
public string Variant { get; set; }
}
So I am not to sure what is going wrong here. My list is being passed in as null. I am not to keen on passing json objects to the controller but I believe I have the gist of what I need.
Could someone please point me in the right direction?
I found the issue. My data needed to be passed in the following way in my AJAX request. Can't believe I missed this honestly.
$.ajax({
cache: false,
url: '/Update/GetSchematicsForSelectedVariants',
type: 'POST',
data: {'ListOfVariants' : items},
success: function (data) {
alert("success");
}
});
Thank you everyone for your comments it helped point me in the right direction.
Related
I have a javascript function that is creating a model that includes an array of objects and sending that data to my MVC controller with an AJAX POST request. For some reason, it seems that there is a limit on the size of that array that can be passed to the controller though, which though experimentation, seems to be between 450 and 500 objects in my case. Once it's larger than that threshold, the controller will just receive a null value. Is there some configuration or workaround that can be done to remove or work around this limitation?
I've already tried several web.config based "solutions" that a lot of people have proposed on similar SO questions to no avail (I think those may be applicable only for .Net Framework's version of ASP.NET, not .NET Core).
Javascript:
var i = 0;
$("#SupplierNumber option").each(function () {
var supplierNumber = {};
supplierNumber.Value = $(this).val();
supplierNumber.text = $(this).val();
supplierNumbers.push(supplierNumber);
//Below limits max size for testing
i = i + 1;
if (i > 450) {
return false;
}
});
//Other non-array values gathered here
var model = {
"SupplierNumbers": supplierNumbers,
//... other non-array values added to model
}
$.ajax({
type: "POST",
url: "/Administration/TestPost",
data: model,
dataType: "json",
success: function (data) {
alert("Finished");
}
});
Controller:
[HttpPost]
public async Task<IActionResult> TestPost(TestViewModel model)
{
//model is null here when array is > 500 in size
return Json(new { success = true });
}
Try this before you use JSON.stringify!
I had exactly the same problem. All I needed to do was the following:
In my Startup.cs I added the following lines in ConfigureServices:
services.Configure<FormOptions>(options =>
{
options.ValueCountLimit = int.MaxValue;
options.ValueLengthLimit = int.MaxValue;
});
Here is two solutions:
First demo,use json type data,we usually use this way to pass array in ajax(pass json type data,need to use contentType: 'application/json' in ajax and use [FromBody] in action):
IndexViewModel:
public class IndexViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
Controller:
[HttpGet]
public IActionResult TestAjax() {
return View();
}
[HttpPost]
public IActionResult TestAjaxWithJsonData([FromBody]List<IndexViewModel> l) {
return Ok();
}
View:
<button onclick="postdata1()">submit(jsondata)</button>
#section scripts{
<script type="text/javascript">
function postdata1() {
var a = [];
for (var i = 0; i < 500; i++) {
var indexViewModel = {};
indexViewModel.Id = i;
indexViewModel.Name = "name" + i;
a.push(indexViewModel);
}
var data = JSON.stringify(a);
$.ajax({
type: "POST",
url: 'TestAjaxWithJsonData',
data: data,
contentType: 'application/json'
}).done(function (data) {
});
}
</script>
}
result:
Second demo,use FormData:
Controller:
[HttpPost]
public IActionResult TestAjaxWithFormdata(List<IndexViewModel> l)
{
return Ok();
}
View:
<button onclick="postdata2()">submit(formdata)</button>
#section scripts{
<script type="text/javascript">
function postdata2() {
var formdata = new FormData();
for (var i = 0; i < 500; i++) {
formdata.append("l[" + i + "].Id", i);
formdata.append("l[" + i + "].Name", "name" + i);
}
$.ajax({
type: "POST",
url: 'TestAjaxWithFormdata',
cache: false,
contentType: false,
processData: false,
data: formdata,
}).done(function (data) {
});
}
</script>
}
result:
I dont know what is the exact problem but you can try this solution. Try to pass data as a sting into action after that Deserialize tht string to object.
var model = {
"SupplierNumbers": supplierNumbers,
//... other non-array values added to model
}
$.ajax({
type: "POST",
url: "/Administration/TestPost",
data: {"data":JSON.stringify(model)},
dataType: "json",
success: function (data) {
alert("Finished");
}
});
on controller side you can Deserilize this string to model.
[HttpPost]
public async Task<IActionResult> TestPost(string data)
{
TestViewModel model=DeserializeObject<TestViewModel>(data);
return Json(new { success = true });
}
We need to set the value count limit and length.
Please Add below code in startup.cs --- It is working for me
services.AddMvc(options =>
{
options.MaxModelBindingCollectionSize = 100000;
});
services.Configure<FormOptions>(options =>
{
options.ValueCountLimit = int.MaxValue;
options.ValueLengthLimit = int.MaxValue;
options.MultipartHeadersLengthLimit = int.MaxValue;
});
After some more searching, I was able to figure out that this is a configuration issue within ASP.NET Core. By default, the max number of values in a complex model that can be bound is 1024. Adding the option below in the ConfigureServices method of the Startup class will allow you to increase this limit to whatever you need (MSDN).
services.AddMvc(options =>
{
options.MaxModelBindingCollectionSize = 100000;
})
Also, something else that I found that people might find useful when facing this problem, but with a form submit action, is the below option that goes in the same method mentioned above (source).
services.Configure<FormOptions>(options => options.ValueCountLimit = 100000);
I've got a piece of JavaScript on a webpage that allows a user to scan in serial numbers and then it should send those to a webmethod where a database records it and a txtfile gets made.
It doesn't matter what's in the webmethod, because the code never runs. (Even removing the entire method and just make it change a bool to true as an example returns the same error). Here is the Js:
function sendingReady() {
saveSerialNumbers();
var employeeNr = document.getElementById("userCode").textContent;
var productNr = document.getElementById("productCode").textContent;
var cnt = {
employeeNumber: employeeNr,
productNumber: productNr
};
$.ajax({
type: "POST",
url: "WebServices.asmx/sendingReady",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({
'cnt': cnt
}),
success: function() {
console.log("Success sendingReady")
},
error: function() {}
});
var succes = "succes";
localStorage.setItem("SuccesVerzenden", succes);
}
function saveSerialNumbers() {
var scannedserials = [];
var errorchoises = [];
var Table = document.getElementById("SerialListContainer");
var rowLength = Table.rows.length;
for (i = 0; i < rowLength; i++) {
var row = Table.rows[i];
var serialnumber = row.childNodes[0].textContent;
scannedserials.push(serialnumber);
var errorChoice = row.childNodes[1].childNodes[0].value;
errorchoises.push(errorChoice);
}
var cnt = {
serialNumber: scannedserials,
sendingErrorcode: errorchoises,
personalNumber: document.getElementById("userCode").textContent,
productNumber: document.getElementById("productCode").textContent
};
$.ajax({
type: "POST",
url: "WebServices.asmx/createSendingCeetisFile",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({
'cnt': cnt
}),
success: function() {
console.log("Success saveSerialNumbers")
},
error: function() {}
});
}
To top function works, I get the "success SendingReady" message in my log. But the bottom function, called by the top one, does not. I've tried everything from sending the data as 4 separate instances, to changing the options in the Ajax call, to changing the recipient webmethod. This is said webmethod:
[System.Web.Services.WebMethod]
public void createSendingCeetisFile(SendingErrors cnt)
{
//unimportant code that doesn't ever run anyway;
}
with sendingErrors being:
public class SendingErrors
{
public string[] serialNumber { get; set; }
public string[] sendingErrorcode { get; set; }
public string[] dollies { get; set; }
public string personalNumber { get; set; }
public string productNumber { get; set; }
}
Dollies isn't being used yet. I'm using IIS and I haven't found any way to debug the server-side; All the IIS logs show is a generic '500' with no further detail.
I'm really hoping I'm missing something obvious, but after trawling through these forums and other sites looking for an answer for slightly over a day I'm kind of losing hope.
Thank you M Adeel Khalid and mplungjan for your help. Though none of your responses was the direct answer the understanding it lend me gave me the idea to try and remove the function from within the other function and just call it directly from the button. this did the trick. I'm still getting an odd error, but the function does everything it is supposed to, saving the records to a database and writing it up in a file for use in a different program.
I'm trying to create bespoke lists in my cshtml file using an ajax call
.ajax({
type: "GET",
cache: false,
url: "#Url.Action("getValidationLists")",
contentType: "application/json",
dataType: "json",
success: function (result) {
var list = result.list;
$.each(list, function (index, value) {
alert(value);
});
}
});
The Controller then collects the data puts it in a List and returns it to my cshtml file using json format. the controller method is below
[HttpGet]
[Authorize]
public JsonResult getValidationLists()
{
List<List<String>> validList = new List<List<String>>();
List<UIReferenceData> results = AddErrorsToModelState<List<UIReferenceData>>(_StaticDataServiceAgent.GetAllAssetTypes());
for (int i = 0; i < results.Count; i++)
{
List<String> resultList = new List<String>();
string id = results[i].ID.ToString();
string name = results[i].Name;
resultList.Add(id);
resultList.Add(name);
validList.Add(resultList);
}
return Json(new
{
validList = validList
}, JsonRequestBehavior.AllowGet);
}
I've tried several different versions but the returning code never gets as far as the alert(value); code.
What am i missing?
The property name is inconsistent with what you are returning from your action:
var list = result.list;
Should be:
var list = result.validList;
However you are returning a List<List<String>> rather than a List<String> too.
I think you need to address both of the above in order to fix.
The JSON response you are returning from your action method looks like this
{
"validList": [
["1", "SomeText"],
["2", "SomeText"],
["3", " SomeText"]
]
}
Your response has a validList property which is an array and each item in an array is again another array with 2 items.
This should work
success: function (result) {
$.each(result.validList, function (index, value) {
console.log(value[0]);
console.log(value[1]);
});
}
I have been playing with SPEAK dialogs lately. So far I like it, but have stumbled across an issue. I have passed with an itemID in the url parameters and I want to display the children of this item in a listcontrol.
My approach was to create a SearchDataSource and set the field "rootItemId" via javascript. This doesn't seem to work. Is there a way to access the SearchDataSource's rootItemId in the PageCode?
Another way I've been using lately is to use Anders Laub's JSON Datasource control here. http://laubplusco.net/creating-simple-sitecore-speak-json-datasource/.
From the JavaScript PageCode you can then do a Ajax call and append in JSON result items to populate your listcontrol, where the listcontrols is bound to the JSON datasources Json property.
$.ajax({
url: "/api/sitecore/RolePermissions/GetAllRoles",
type: "POST",
context: this,
success: function (data) {
var json = jQuery.parseJSON(data);
for (var i = 0; i < json.length; i++) {
var obj = json[i];
this.JsonDS.add(obj);
}
}
});
I managed to do this with query. In pageCode:
public class SelectTitle : PageCodeBase
{
//Fetches DataSource as rendering
public Rendering DataSource { get; set; }
public override void Initialize()
{
var articleid = WebUtil.GetQueryString("article");
if (!String.IsNullOrEmpty(articleid))
{
//Set the query.
this.DataSource.Parameters["query"] =
String.Format("fast:/some/path/*[##id = '{0}']/Elements/*[##templateid = '{1}']", articleid, '{guid}');
}
}
}
I have a jquery interacting with a server side Web Method. The Web method accepts a string 'memID' from the jquery and executes SQL queries based on it. Then I create a class:-
public class Member
{
// Objects of Member. //
public string id { get; set; }
public string HPCode { get; set; }
public string OPfromDate { get; set; }
public string OPthruDate { get; set; }
public Member(string ID, List<string> hpCode, List<string> opfromDate, List<string> opthruDate)
{
id = ID;
for (int j = 0; j < hpCode.Count; j++){ HPCode = HPCode + (hpCode)[j] + '*' };
for (int j = 0; j < opfromDate.Count; j++){OPfromDate = OPfromDate + (opfromDate)[j] + '*' };
for (int j = 0; j < opthruDate.Count; j++){OPthruDate = OPthruDate+ (opthruDate)[j] + '*' };
}
}
This class is used to return the results of my SQL query to the client side:-
return JsonConvert.SerializeObject(member);
I used breakpoints and checked on the client side, indeed it is getting the return values. However I am not sure about what is the best way to parse these values and store them in variables on my javascript side so i can use them for client-side functionalities.
// Ajax function that sends member ID from client side to server side without a post back.
function ajax()
{
$.ajax
({
url: 'Default.aspx/MyMethod',
type: 'POST',
dataType: "json",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ memID: mem_ID }),
success: onSuccess,
fail : onFail
});
}
// If client-to-server communication is successful.
function onSuccess(data)
{
confirm(data.d);
var returnedstring = (data.d);
var jsondata = $.parseJSON(data.d);
}
Now how do I parse the 'data' ?? is there an eval function? or parse function?
Does anybody have any web examples? before this I was only passing back 1 value to my client side, so it was easy to get, now i am confused with multiple values.
UPDATE:-
I tried doing this on my javascript side:-
var returnedstring = (data.d);
var member = data.d.id;
var Hp = data.d.HPCode;
however when I use breakpoints and hover over them with my mouse, i get member and HP as undefined, however the returnedstring has all the correct values.. ... any idea?
SOLUTION (I couldn't figure out the other way suggested in the answers, but this works for me) :-
function onSuccess(data)
{
// stores entire return in one string.
var returnedstring = (data.d);
// parses json returned data
var jsondata = $.parseJSON(data.d);
var member = jsondata.id;
var HpCode = jsondata.HPCode;
}
Because you're using dataType: "json", data is already parsed out of the JSON string. That's why you're able to access data.d in Javascript.
To access the members, you can do something like this:
console.log(data.d.HPCode);