Javascript Ajax call to asp.net webmethod, Internal server error - javascript

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.

Related

Can't pass array of objects to controller by jQuery AJAX

I tried to pass array of objects to controller by jQuery Ajax, but result is null in ASP.NET 5.0.
My data array is what send to controller: regions.
Data constructor is defined in BoundingBoxModel class.
This is my ajax function:
$("body").on("click", "#onClick", function () {
var regions = [];
var arr = Array.prototype.slice.call(document.getElementsByClassName('ui-draggable'));
arr.forEach((tagele) => {
var region = {};
region.Height = tagele.offsetHeight;
region.Width = tagele.offsetWidth;
region.Top = tagele.offsetTop;
region.Left = tagele.offsetLeft;
regions.push(region);
});
$.ajax({
url: '/GenCode/Addregions',
type: "POST",
dataType: "json",
contentType: "application/json;charset=utf-8",
data: JSON.stringify({'regions': regions}),
success: function () {
alert("pass")
},
error: function (jqXhr, json, errorThrown) {
alert(errorThrown);
console.log(errorThrown);
}
});
});
So this is my BoundingBoxModel:
public class BoundingBoxModel
{
public int BoundingBoxId { get; set; }
public double Top { get; set; }
public double Left { get; set; }
public double Height { get; set; }
public double Width { get; set; }
}
This is my action method. It's defined in GenCodeController.
[HttpPost]
public IActionResult AddRegions(List<BoundingBoxModel> regions)
{
JsonResult result = new JsonResult(this.Json(JsonConvert.SerializeObject(regions), System.Web.Mvc.JsonRequestBehavior.AllowGet));
return result;
}
My result is null:
I don't understand why it's happened. Can you help me?
There are some issues that I can see -
I am not sure if you explicitly written this logic but your region object will always have last value of arr because you declare your variable inside loop.
If you are trying to create an array then you should declare your region variable like - var region = []; .Right now it is an object.
You are trying to pass an object and accepting a list in webservice. Either remove the list in parameter in AddRegions service or pass a Array from ajax call.
I resolved my problem by deteting contentType: "application/json;charset=utf-8", line in ajax code.
Using this line make the array of region's type change to string so when i get data in Controller problem was happened.

AJAX POST Data to MVC Controller in ASP.NET Core Always Null When Passing An Object Array Over a Certain Length

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);

Passing JSON array in AJAX call sending null in MVC

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.

Post knockout.js viewmodel to .Net Core (2.0) MVC Controller

Overview:
Currently, I try to create an ASP.NET Core MVC website which gets data from the server on page load. After that, the page uses knockout.js to maintain a viewmodel to update the data sent from the server (in the first step). Finally, there is a button which sends the edited data back to the server (through an AJAX request). But the corresponding value in my server method is always empty.
Current Approach:
First, there is my model class.
public class Order
{
public string Name { get; set; }
public int TemplateId { get; set; }
public decimal Price { get; set; }
public int Contingent { get; set; }
public int MaximumOrder { get; set; }
public int UserOrderCount { get; set; }
public Order() { }
public Order(SnackOffer offer)
{
Name = offer.Template.Name;
TemplateId = offer.Template.SnackTemplateId;
Price = offer.Price;
}
}
In my view I use the model class as a List (List) and load the data like this:
var model = new viewModel();
#(Json.Serialize(Model.Offers)).forEach(function (item, index) {
model.offers.push({
name: item.name,
templateId: item.templateId,
contingent: ko.observable(item.contingent),
userOrderCount: ko.observable(item.userOrderCount),
price: item.price,
maximumOrder: item.maximumOrder
});
})
The viewModel is defined like this (shortend for readability):
function viewModel() {
var self = this;
self.offers = ko.observableArray();
}
Now after someone hits the mentioned update button I call this javascript function:
self.ConfirmOrder = function () {
var data = ko.toJSON(self.offers);
$('#overlay').css('display', 'block');
$.ajax({
type: 'post',
url: '/Snack/ConfirmOrder',
data: data,
contentType: 'application/json; charset=utf-8',
success: function (result) {
$('#overlay').css('display', 'none');
},
error: function (result) {
console.log(result);
$('#overlay').css('display', 'none');
}
});
}
Here you can see that I use the ko.toJSON method to convert the observableArray to a JSON String and use this string as the data argument for the ajax post.
The ConfirmOrder method in the MVC Controller looks like this currently:
[HttpPost]
public void ConfirmOrder(List<OrderSnackViewModel.Order> offers)
{
foreach (var item in offers)
{
_logger.LogInformation(item.Name);
}
}
There is no logic yet cause the offers list is created (so not null) but the count of list items is always 0.
In a concret example this is the JSON string I receive from the server while load the view:
[{"name":"Test","templateId":1,"price":1.94,"contingent":4,"maximumOrder":7,"userOrderCount":0},{"name":"Test 1","templateId":2,"price":1.50,"contingent":30,"maximumOrder":7,"userOrderCount":0}]
And this is the string i produce with the ajax call:
[{"name":"Test","templateId":1,"contingent":4,"userOrderCount":0,"price":1.94,"maximumOrder":7},{"name":"Test 1","templateId":2,"contingent":30,"userOrderCount":0,"price":1.5,"maximumOrder":7}]
What have I tried already:
I have tried to use FromBody in my MVC Controller
I have tried to prefix the JSON output with the name offer so my controller method can map the JSON string items to the object. (e.g. data = '{ "offers":' + data + '}'; )
I have tried to rename the Properties of my model to match exactly the JSON names. So I renamed Name to name and Contingent to contingent and so on.
I have tried to use an array instead of the List in the MVC controller action
Is there a master somewhere which can help me with this problem?
(If you need some more information please do not hesitate to ask)
Thanks to the input of #adiga I have found the solutions for (my) error.
[HttpPost]
public JsonResult ConfirmOrder([FromBody]List<Order> offers)
{
_logger.LogInformation("COUNT -> " + offers.Count());
foreach (var item in offers)
{
_logger.LogInformation(item.Name);
}
}
This is the working solution. I thought I already have tried it but maybe I have forgoten the content-type for the ajax post.
var data = ko.toJSON(self.offers);
$('#overlay').css('display', 'block');
$.ajax({
type: 'post',
url: '/Snack/ConfirmOrder',
data: data,
contentType: 'application/json; charset=utf-8',
success: function (result) {
//location.reload();
$('#overlay').css('display', 'none');
},
error: function (result) {
console.log(result);
$('#overlay').css('display', 'none');
}
});
Thanks again for all responses!

How to parse a JSON object ? (From server-side to client-side...javascript)

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);

Categories