ASP.NET MVC JsonResult return 500 - javascript

I have this controller method:
public JsonResult List(int number) {
var list = new Dictionary <int, string> ();
list.Add(1, "one");
list.Add(2, "two");
list.Add(3, "three");
var q = (from h in list where h.Key == number select new {
key = h.Key,
value = h.Value
});
return Json(list);
}
On the client side, have this jQuery script:
$("#radio1").click(function() {
$.ajax({
url: "/Home/List",
dataType: "json",
data: {
number: '1'
},
success: function(data) {
alert(data)
},
error: function(xhr) {
alert(xhr.status)
}
});
});
I always get an error code 500. What's the problem?
Thank you

If you saw the actual response, it would probably say
This request has been blocked because
sensitive information could be
disclosed to third party web sites
when this is used in a GET request. To
allow GET requests, set
JsonRequestBehavior to AllowGet.
You'll need to use the overloaded Json constructor to include a JsonRequestBehavior of JsonRequestBehavior.AllowGet such as:
return Json(list, JsonRequestBehavior.AllowGet);
Here's how it looks in your example code (note this also changes your ints to strings or else you'd get another error).
public JsonResult List(int number) {
var list = new Dictionary<string, string>();
list.Add("1", "one");
list.Add("2", "two");
list.Add("3", "three");
var q = (from h in list
where h.Key == number.ToString()
select new {
key = h.Key,
value = h.Value
});
return Json(list, JsonRequestBehavior.AllowGet);
}

While JustinStolle's answer solves your problem, I would pay attention to the error provided from the framework. Unless you have a good reason to want to send your data with the GET method, you should aim to send it with the POST method.
The thing is, when you use the GET method, your parameters gets added to your request url instead of added to the headers/body of your request. This might seem like a tiny difference, but the error hints why it's important. Proxy servers and other potential servers between the sender and the receiver are prone to logging the request url and often ignore the headers and/or body of the request. This information is also often regarded as non important/secret so any data exposed in the url is much less secure by default.
The best practice is then to send your data with the POST method so your data is added to the body instead of the url. Luckily this is easily changed, especially since you're using jquery. You can either use the $.post wrapper or add type: "POST" to your parameters:
$.ajax({
url: "/Home/List",
type: "POST",
dataType: "json",
data: { number: '1' },
success: function (data) { alert(data) },
error: function (xhr) { alert(xhr.status) }
});

Related

.Net Core v3.1 POSTing a large JSON object to a Razor Page handler

I have the following JavaScript:
var ids = [
"ed4bbe0e-d318-e811-a95f-000d3a11f5ee",
"386c9468-d11b-e811-a95d-000d3a11ec14",
"2913f317-991d-e811-a95d-000d3a11ec14"
];
$.ajax({
method: 'POST',
url: `/Jobs?handler=CreateJobsInQBO`,
dataType: 'json',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
// contentType: 'application/json',
data: { jobIds: ids }
})
POSTing to the Razor Page handler below
public async Task<JsonResult> OnPostCreateJobsInQBO(IEnumerable<string> jobIds) {
Result<List<Job>> result;
if (jobIds == null || !jobIds.Any()) {
result = "No jobs were submitted.";
} else {
result = await DoStuffAsync(jobIds);
}
return new JsonResult(result);
}
This works without issue.
The problem is that when my JavaScript array is large, roughly 3000 items, I get null for the incoming handler parameter value. I've tried setting the ajax contentType to application/json and also using JSON.stringify on the object before it's sent, but they don't seem to make a difference. I also tried setting [FormBody] on the parameter in the handler function, but again, it didn't work.
I know I'm missing something simple here. I just need a way to POST an array of string to a handler method that has roughly around 5000 items. Preferably without using the application/x-www-form-urlencoded content type as I think that is what's causing the large array to not work.
The default value of ValueCountLimit is 1024. It is a limit for the number of form entries to allow.
If the value count exceed 1024, you should increase it in Startup.cs
services.Configure<FormOptions>(options =>
{
options.ValueCountLimit = int.MaxValue;
});

Pass a Javascript ES6 Map() to an MVC Controller

I am using the Map() functionality in ES6 to create a list of keypair values, making an ID number to a boolean value. I want to pass this Javascript object to an MVC 4 Controller.
Here's my Javascript:
var bankHolidays = new Map();
$('.bank-holiday-switch').each(function () {
var id = $(this).attr('id');
var isChecked = $(this).is(':checked');
bankHolidays.set(id, isChecked);
});
$.ajax({
url: '/AdminPanel/Settings/SaveBankHolidays',
type: 'POST',
data: { bankHolidays: bankHolidays },
success: function (result) {
alert("Success");
}
});
I can console.log() the map object and see that it's being created as intended. However, when I pass it to this MVC Controller:
[HttpPost]
public JsonResult SaveBankHolidays(Dictionary<int, bool> bankHolidays)
{
// DO stuff
}
..no error is thrown, but it just says the bankHolidays dictionary has 0 values in it. I can call other Actions in that Controller without issue. I have tried many different combinations of Dictionary<string, bool> to no avail.
Can somebody tell me what I am doing wrong?
In a http negotiation, xhr in this case, we must send strings, so you need some string representation of Map(), the best option, in my opinion, is to use a JSON stringify in some way, because the parse of JSON have a broad support among server side code:
var bankHolidays = new Map();
bankHolidays.set(1, 2);
bankHolidays.set(3, 4);
var result = JSON.stringify([...bankHolidays]);
console.log(result)
In your code something like :
$.ajax({
url: '/AdminPanel/Settings/SaveBankHolidays',
type: 'POST',
data: JSON.stringify([...bankHolidays]),
success: function (result) {
alert("Success");
}
});
In backend you have to parse the response, see this.

Use a dictionary type in Javascript [Ajax]

I am building an ASP.NET MVC application It currently has a button that once clicked does an Ajax call to the controller as so:
function getData() {
$.ajax({
url: "/Home/GetData/",
type: "POST",
contentType: 'application/json',
success: function (data){
//need to do stuff here
}
});
}
The controller then initializes a class, converts it to XML and then converts that to the following dictionary (There is a reason for this):
public ActionResult GetData()
{
List<People> peeps = GetPeeps();
string xml = ToXml(peeps);
Dictionary<string,List<string>> stuff = ToDictionary(xml);
return Json(stuff);
}
I would like to be able to 'Do stuff' with this data client side with javascript.
The APIs I have to work with Server side return XML data.
The APIs I have to work with Client side require string arrays. (Hence the conversions)
Is there a way to use the dictionary i've defined above client side? Could someone perhaps expand from this (if possible) to add to the ajax call a small method that prints the contents of the dictionary to a message box? just to give me a starting point from how to use the dictionary in javascript.
Thanks in advance
You can try in the ajax call as follow:
function getData() {
$.ajax({
url: "/Home/GetData/",
type: "POST",
contentType: 'application/json',
success: function (data){
console.log(data.key1); // value for key1
//or to list all values
for(var key in data){
console.log(data[key]);
}
}
});
}
Controller (for explanation purposes):
public ActionResult GetData()
{
//List<People> peeps = GetPeeps();
//string xml = ToXml(peeps);
//Dictionary<string,List<string>> stuff = ToDictionary(xml);
Dictionary<string,List<string>> stuff = new Dictionary<string, List<string>>
{
{"key1", new List<string> {"a", "b", "c"}},
{"key2", new List<string> {"d", "e", "f"}},
};
return Json(stuff);
}
I hope this is clear enough. Let me know how you go :)

Setting string in javascript function in ASP.NET MVC give NullReferenceException

Inside my MVC view I have javascript that is executed by a button click. I'm trying to set a string to a random set of characters which I can get to work fine but when I try and set that string to 'randomchars' string inside the javascript I get a NullReferenceException when I try and run the view.
Below is the code snippet, the CreateRString is where the model parameter (RString) is set to the random string.
<script type="text/javascript">
function showAndroidToast(toast) {
var url = '#Url.Action("CreateRString", "Functions")';
$.ajax({ url: url, success: function (response) { window.location.href = response.Url; }, type: 'POST', dataType: 'json' });
var randomchars = '#(Model.RString)';
}
</script>
Is the syntax correct? I'm not too sure why it's getting the NULL.
The javascript is executed after the page been delivered to the client (i.e. web browser). Your razor code here is executed on the server before the page is sent to the client. Therefore, the ajax method will execute after you try to access Model.RString
To fix this you can either call CreateRString on the server, or you can set randomchars by using the response in the success callback.
To explain option 2 a bit further. You could do something like this:
//Action Method that returns data which includes your random chars
public JsonResult CreateRString()
{
var myRandomChars = "ABCDEF";
return new JsonResult() { Data = new { RandomChars = myRandomChars } };
}
//The ajax request will receive json created in the CreateRString method which
//contains the RandomChars
$.ajax({ url: url, success: function (response) {
var randomchars = response.Data.RandomChars;
window.location.href = response.Url;
}, type: 'POST', dataType: 'json' });
More specifically, the razor calls #Url.Action("CreateRString", "Functions") and #(Model.RString) execute first on the server.
Then showAndroidToast executes in the client's browser when you call it.

JQuery Ajax POST no longer hits ServerSide asp.net Method after adding parameters

Before adding any parameters I had this POST method hitting my serverside code whenever a user would set focus from one control to another. This was good but i need to pass data of the id and value. These values are being populated from what gather in my failure growl.
The issue is that I don't exactly know why it will no longer hit my serverside routine. I did look around stackoverflow a good deal for some help, i did clean up a few things but I couldnt quite pinpoint exactly where my issue is.
$(document).ready(function () {
var id;
var value;
$(".tpControl").blur(function () {
id = this.id;
value = $(this).val();
var postdata = { identifier: id, controltext: value };
$.ajax({
type: "POST",
url: "TimePoints.aspx/ClientSideSave",
contentType: "application/json; charset=utf-8",
data: postdata,
dataType: "json",
success: function (msg) {
if (msg.hasOwnProperty("d")) {
OnSuccess(msg.d);
} else {
OnSuccess(msg);
}
},
error: OnFailure
});
});
function OnSuccess(result) {
$.growlUI('AutoSave Successful');
}
function OnFailure(result) {
$.growlUI("ID: " + id, "Answer: " + value);
}
});
My Server side is pretty simple
[WebMethod]
public static void ClientSideSave(string identifier, string controltext)
{
//Bunch of code, shouldn't affect anything.
}
Thank you in advance. Any help would be great, im pretty new to the world of Jquery and Ajax.
You were close, but remember you are posting JSON, not form value collections. This means JSON strings are quoted during transport and in your example, will be quoted on the backend, probably not what you really want:
var postdata = "{ 'identifier': 'id', 'controltext': 'value' }";
3 mistakes to avoid when using jQuery with ASP.NET AJAX
If you want use JSON(JavaScript Object Notation) the right way, then you should follow this example:
Using complex types to make calling services less… complex

Categories