Why does POST without parameters not return JSON - asp.net-mvc

I have a controller method
[HttpPost]
public ActionResult GetUserData()
{
return Json(GetCurrentUser());
}
I'm calling it $.ajax() through a method like this:
ServerCall: function (method, args, callback) {
$.ajax({
type: 'POST',
url: method,
data: JSON.stringify(args),
contentType: 'application/json;charset=utf8',
dataType: 'json',
success: function (result) {
if (callback) {
callback(result);
}
},
error: function (err) {
}
});
}
with the call being:
ServerCall('GetUserData', null, function(data){
});
As it is, when I make this call, $.ajax returns with success, but 'data' is null. Debugging, responseText is empty. On the server side, GetUserData is called, and it is returning a properly formatted Json object (I've gone so far as to create my own JSON ActionResult and verified that data is indeed being written to the response stream.
If I add a dummy parameter to the server side method:
[HttpPost]
public ActionResult GetUserData(string temp)
{
return Json(GetCurrentUser));
}
everything works perfectly. Browser is IE8. My question is, can anyone explain why this is happening?
UPDATE:
Note workaround solution below: I'd still be interested in knowing the root cause.

No repro.
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult GetUserData()
{
return Json(new { foo = "bar" });
}
}
Index.cshtml view:
<script type="text/javascript">
var serverCall = function (method, args, callback) {
$.ajax({
type: 'POST',
url: method,
data: JSON.stringify(args),
contentType: 'application/json;charset=utf8',
dataType: 'json',
success: function (result) {
if (callback) {
callback(result);
}
},
error: function (err) {
}
});
};
serverCall('#Url.Action("GetUserData")', null, function (data) {
alert(data.foo);
});
</script>
result: 'bar' is alerted (as expected).

I was able to reproduce using Darin's code in IE8. While I don't know the root cause, I think it has something to do with how IE8 JSON.stringify handles null. Changing
data: JSON.stringify(args)
to
data: args ? JSON.stringify(args) : null
fixed the problem.
Note, the problem is intermittent - I was seeing failures in about one out of every ten calls. With the change, over 100 tests, the failure rate was zero.

Related

Send data from js to controller

I have this ajax:
function sendData() {
var question = (document.getElementById('question').value).toString();
var c = (document.getElementById('c').value).toString();
$.ajax({
url: '/Home/InsertData',
type: 'POST',
data: {question:question, c:c},
// data: {},
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function () {
alert('suc');
},
error: function (error) {
alert('error');
}
});
}
in my HomeController, I have the function:
[HttpPost]
public void InsertData(string question, string c)
//public void InsertData()
{
this.insertDataToCustomers(question, c);
}
when I run it, I got an error of:
POST http://localhost:2124/Home/InsertData 500 (Internal Server Error)
If I didn't ask for input values in InsertData function and didn't send data in the ajax, it works. why can't I send data to InsertData function?
p.s. There are values in question and c
thank you!
Remove this:
contentType: 'application/json; charset=utf-8',
You are not sending any JSON to the server, so this is an incorrect content type for the request. You are sending a application/x-www-form-urlencoded request.
So:
function sendData() {
var question = $('#question').val();
var c = $('#c').val();
$.ajax({
url: '/Home/InsertData',
type: 'POST',
data: { question: question, c: c },
success: function () {
alert('suc');
},
error: function (error) {
alert('error');
}
});
}
Another problem with your code is that you indicated dataType: 'json' which means that you expect the server to return JSON but your controller action doesn't return anything. It's just a void method. In ASP.NET MVC controller actions should return ActionResults. So if you want to return some JSON for example to indicate the status of the operation you could have this:
[HttpPost]
public ActionResult InsertData(string question, string c)
{
this.insertDataToCustomers(question, c);
return Json(new { success = true });
}
Of course you could return an arbitrary object which will be JSON serialized and you will be able to access it in your success AJAX callback.

Ajax call returns parsererror

I have a Controller with the Action Like This
public ActionResult UpdateCompanyInfo(Parameter parameter)
{
bool result = false;
if(ModelState.IsValid)
{
bla bla bla
}
return Json(result, JsonRequestBehavior.AllowGet);
}
I also have a javascript function:
function blabla(){
$.ajax({
type: 'POST',
url: "What Ever",
async: false,
data: JSON.stringify(jsonObject),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (succeed) {
if (succeed) {
// Some Code
}
},
error: function () {
//Some Other Code
}
});
}
the javascript function calls properly and it hits Action method with the parameter (No problem yet!).
but when the Action method returns bool object using Json function, it hits the javascript error function response with the following parameters:
readyState 4
responseText "true"
status 200
statusText "parsererror"
jQuery15101815967692459196_1384707824272 was not called
I also tried
return Json(new { result }, JsonRequestBehavior.AllowGet); and
return Json(new {succeed = result }, JsonRequestBehavior.AllowGet); and
return Json(new {succeed = result.ToString() }, JsonRequestBehavior.AllowGet);
but they did not work too.
in addition i have an exactly the same function in another controller which calls another same javascript function but it works properly. I don't know what's wrong with it. am i missing something?
----------- EDIT --------------
I don't know why! but when i remove the dataType: 'json', from the Ajax call, and put return Json(result, JsonRequestBehavior.AllowGet); in action method, it works properly. could someone explain it to my "why?"
Actually it seems there is a bug in jquery 1.5.1 and 1.5.0 (which does not exist in previous versions).
In fact when you use dataType: 'json' it tries to parse json as a script and you should use dataType: 'text/json' instead. see this link.
The data returned from the server might not be of json type. So you can use below two method to overcome.
Option 1:
Use dataType: 'text' as part of ajax request.
Option 2:
Remove the dataType from ajax request as it will try to infer it based on the type of the response.
From your response, In controller, there is no json encoded data, jsonformat looks like, {'responseText':'your text here '}
You are only returning a single value which the JSON parser in JS will not accept. Try this:
public ActionResult UpdateCompanyInfo(Parameter parameter)
{
bool result = false;
if(ModelState.IsValid)
{
bla bla bla
}
return Json(new { success = result }, JsonRequestBehavior.AllowGet);
}
The anonymous object returned by JSON will look like this:
[{ "success": true }]
Which you can then deal with in your success handler, like this:
success: function (data) {
if (data.success) {
// Some Code
}
else {
// Bad things going down
}
},

Received parameter from ajax POST empty in controller + passed parameter in firebug MVC 4

I have looked over the net to figure out what my mistake is. All suggestions I found I tried, without any succes. I access the httppost action in my controller but the parameters stays empty.
AJAX function
var dataPost = { 'id': id, 'val': val };
debugger;
$.ajax({
type: 'POST',
url: '/Extensions/UpdateJson',
data: dataPost ,
contentType: 'json',
success: function () {
alert("succes");
},
error: function () {
alert("error");
}
});
On debug DataPost is populated.
Controller
[HttpPost]
public ActionResult UpdateJson(string id, string val)
{
//do stuff
return Json(true);
}
The parameters I used in my controller have the same name as in my Ajax function. The format passed is json, I have also tried populating my data with:
var dataPost = { 'id': 'id', 'val': 'val' };
But this doesn't make any difference. I have also tried to work with a Class, like -->
Class
public class ScheduleData
{
public string id { get; set; }
public string val { get; set; }
}
Controller
public ActionResult UpdateJson(ScheduleData data)
{//Do something}
Any help would be appreciated. Thanks in advance
The format passed is json
No, not at all. You are not sending any JSON. What you do is
data: { 'id': id, 'val': val }
But as the documentation clearly explains this is using the $.param function which in turn uses application/x-www-form-urlencoded encoding.
So get rid of this contentType: 'json' property from your $.ajax call.
Or if you really wanna send JSON, then do so:
var dataPost = { 'id': id, 'val': val };
$.ajax({
type: 'POST',
url: '/Extensions/UpdateJson',
data: JSON.stringify(dataPost),
contentType: 'application/json',
success: function () {
alert("succes");
},
error: function () {
alert("error");
}
});
Things to notice:
usage of JSON.stringify(dataPost) to ensure that you are sending a JSON string to the server
contentType: 'application/json' because that's the correct Content-Type value.

Making an Ajax call to the controller

I'm using MVC 2 and trying to make an ajax call to the controller method.
Controller:
[HttpGet]
public ActionResult FirstAjax()
{
return View();
}
[HttpPost]
public ActionResult FirstAjax(string a)
{
return Json("chamara", JsonRequestBehavior.AllowGet);
}
View:
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var serviceURL = '<%= Url.Action("FirstAjax", "AjaxTest") %>';
$.ajax({
type: "POST",
url: serviceURL,
data: param = "",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: successFunc,
error: errorFunc
});
function successFunc(data, status) {
alert(data);
}
function errorFunc() {
alert('error');
}
});
</script>
</head>
In above code please notice my controller. to get the code working i had to add to methods with HTTPPOST and HTTPGET and even the parameter a is not related i just added it because i can not add two methods with the same signature.
I guess this might not be the correct way to do this. please explain the most suitable approach for this kind of code.
UPDATE:
adding a single method with out POST and GET does not work. It just print the string "chamara" on the page.alert not firing
public ActionResult FirstAjax()
{
return Json("chamara", JsonRequestBehavior.AllowGet);
}
From your explanation I think the code what you need is like :
AjaxTestController.cs
[HttpGet]
public ActionResult FirstAjax()
{
return Json("chamara", JsonRequestBehavior.AllowGet);
}
Script:
<script type="text/javascript">
$(document).ready(function () {
var serviceURL = '<%= Url.Action("FirstAjax", "AjaxTest") %>';
$.ajax({
type: "GET",
url: serviceURL,
success: successFunc,
error: errorFunc
});
function successFunc(data) {
alert(data);
}
function errorFunc(xhr, status, err) {
alert('error');
}
});
</script>
Since you cannot have two methods with the same name and signature you have to use the ActionName attribute:
UPDATE:
[HttpGet]
public ActionResult FirstAjax()
{
Some Code--Some Code---Some Code
return View();
}
[HttpPost]
[ActionName("FirstAjax")]
public ActionResult FirstAjaxPost()
{
Some Code--Some Code---Some Code
return View();
}
And please refer this link for further reference of how a method becomes an action. Very good reference though.

jQuery.parseJSON not working for JsonResult from MVC controller action

I am trying to use jQuery.parseJSON to parse out the return value from an MVC3 controller action.
Controller:
[HttpPost]
public JsonResult LogOn(LogOnModel model, string returnUrl)
{
.. do stuff ..
if (errors.Count() < 0)
{
return Json(new object[] { true, model, errors });
}
return Json(new object[] { false, model, errors });
}
jQuery:
$.ajax({
url: form.attr('action'),
type: "POST",
dataType: "json",
data: form.serialize(),
success: function (data) {
var test = jQuery.parseJSON(data);
}
});
Json result from fiddler:
Content-Type: application/json; charset=utf-8
[false,{"UserName":"1","Password":"2","RememberMe":false},[{"Key":"","Errors":[{"Exception":null,"ErrorMessage":"The
user name or password provided is incorrect."}]}]]
Fiddler can parse the results:
The call to jQuery.parseJSON is returning null.
My questions is, how can I parse the json return value into an object?
Thanks!
You don't need to call parseJSON in your success handler, because ajax will have already parsed the JSON result (it does this automatically because you specified dataType:'json') into your array.
However, I'd recommend returning some sort of result object (whether you create an actual class in C# or use an anonymous type).
[HttpPost]
public JsonResult LogOn(LogOnModel model, string returnUrl)
{
.. do stuff ..
if (errors.Count() < 0)
{
return Json(new { success=true, model, errors });
}
return Json(new { success=false, model, errors });
}
and at the client
$.ajax({
url: form.attr('action'),
type: "POST",
dataType: "json",
data: form.serialize(),
success: function (result) {
alert(result.success);
// also have result.model and result.errors
}
});
You are actually returning an array of objects and they shoould be accessed like this in the success function:
var booleanValue = data[0];
var yourModel = data[1];
var yourErrors = data[2];
I did give #HackedByChinese an up vote because naming the properties might be a better way to go about it in the end. Howvbere this will solve your immediate problem.

Resources