Below is my AJAX GET request that is trying to pass few parameters including a javascript object to a mvc controller but the object is always received as null:
var sort = { column: 'UserName', order: 'desc' };
var sortParameter = JSON.stringify(sort);
$.ajax({
url: '#Url.Action("GetUsers", "Account")',
cache: false,
type: 'GET',
contentType: 'application/json; charset=utf-8',
data: { skipRecords: vm.pageIndex * 1000, sortParam: sortParameter },
success: function (data) {
}
});
The controller method looks like below:
[HttpGet]
public JsonResult GetUsers(int skipRecords, Sort sortParam, string userName = null)
{
}
Also below is the Sort class defined:
public class Sort
{
public string column { get; set; }
public string order { get; set; }
}
If I dont use JSON.stringify and pass just the javascript object, below is the request that gets sent:
GET /Account/GetUsers?skipRecords=0&sortParam%5Bcolumn%5D=UserName&sortParam%5Border%5D=desc&_=1408990051727 HTTP/1.1
You're probably looking for:
var sortParameter = { column: 'UserName', order: 'desc' };
$.ajax({
url: '#Url.Action("GetUsers", "Account")',
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
skipRecords: vm.pageIndex * 1000,
sortParam: sortParameter }),
success: function (data) {
}
});
The reason your code doesn't work is because if you don't JSON.stringify the entire result, it is passed as a querystring encoded. You can't pass JSON as a value in a querystring encoded value.
Querystring encoded (Post or Get) looks like: a=1&b=2&c=3
So your querystring would look like skipRecords=5&sortParam={column:'UserName',order:'desc' }
MVC Won't double decode querystring and json.
Use POST and prepend [FromBody] to your 'Sort' object parameter in your action method.
Related
I am trying to pass an array of integers from my client-side javascript to server-side C# using ajax. However it always comes up as null in code-behind. I can't seem to find the issue here. I had a similar ajax method but with an array of strings and it works, but it doesn't with integers?
My ajax method:
var theList = [1,2,3,4,5];
$.ajax({
type: 'POST',
url: 'MyPage?handler=SaveList',
dataType: 'json',
contentType:'application/json; charset=utf-8',
headers: {
RequestVerificationToken:
$('input:hidden[name="__RequestVerificationToken"]').val()
},
data: JSON.stringify({ theList: theList }),
success: function(data){
alert("Success");
}
});
My code-behind:
public JsonResult OnPostSaveList([FromBody]int[] theList) //<<<Returns 'null'
{
foreach(int data in theList){
//save to datebase
}
return new JsonResult("Done");
}
The issue here is I get a null value from theList in the code-behind.
Checking the JSON.stringify, it seems to be passing "[1,2,3,4,5]". Not sure if there is a type mis-match here.
The Max value of int32 is 2147483647, while 1609430400000 is out of range, so you receive the null value.
Instead of int[], you can use long[] to receive the value.
var theList = [1609430400000, 1609516800000, 1609603200000];
$.ajax({
type: 'POST',
url: 'Index?handler=SaveList',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
headers: {
RequestVerificationToken:
$('input:hidden[name="__RequestVerificationToken"]').val()
},
data: JSON.stringify(theList),
success: function (data) {
alert("Success");
}
});
Handler:
public JsonResult OnPostSaveList([FromBody] long[] theList) //<<<Returns 'null'
{
foreach (var data in theList)
{
//save to datebase
}
return new JsonResult("Done");
}
Request Payload:
Result:
I have this list of objects which I need to send from my angularjs javascript code:
var dataToSend = [{
SubId: "c9cb1d3e-8c32-4a9e-8f0d-0008196776de",
CustomerName: "Blah"
}, {
SubId: "aaaa1d3e-8c32-4a9e-8f0d-0008196776de",
CustomerName: "Blah2"
}]
I've tried these different variations but none of them are working:
1.
$http.post("url",
{
dataType: 'json',
headers: {
contentType: "application/json; charset=utf-8",
},
method: "POST",
data: dataToSend,
}).then...
2.
$http.post("url",
{
data: $.param(dataToSend),
}).then...
3
$http.post("url",
{
data: angular.toJson(dataToSend),
}).then...
4
$http.post("url",
{
data: { customers: dataToSend },
}).then...
5
$http.post("url",
{
data: JSON.stringify({ customers: dataToSend }),
}).then...
My API side code is (I have tried with [FromBody] attribute but no luck there):
[HttpPost]
public async Task<JsonResult> CreateCustomers(List<Customer> customers)
{
// customers is always null
}
And this is my Customer.cs:
public partial class Customer
{
public System.Guid SubId { get; set; }
public string CustomerName { get; set; }
}
Can you please help me? I have tried posting to CreateCustomers(Customer c) without using a list and its working as expected. But when I use a list, its always coming as null on the other side.
EDIT:
$.ajax is working but $http.post isn't. Any idea why?
var request = $.ajax({
dataType: "json",
url: "url",
method: "POST",
data: { '': dataToSend }});
Are you sending JSON ( Include dataType: 'json')
$http({
url: "url",
dataType: 'json',
method: 'POST',
data: dataToSend,
headers: {
contentType: "application/json; charset=utf-8",
}
})
In C# add FromBody in parameter
[HttpPost]
public async Task<JsonResult> CreateCustomers([FromBody]]List<Customer> customers)
{
// customers is always null
}
More on Ajax parameters
contentType is the type of data you're sending, so application/json; charset=utf-8 is a common one, as is application/x-www-form-urlencoded; charset=UTF-8, which is the default.
dataType is what you're expecting back from the server: json, html, text, etc.
This should work. post full code if you face issue
use [ModelBinder] in front of your param.
[HttpPost]
public async Task<JsonResult> CreateCustomers([ModelBinder]List<Customer> customers)
{
// customers is always null
}
Web API only uses model binding for simple types, falling back on formatters for everything else. Adding [ModelBinder] forces the complex types to use model binding anyway.
Your post data is not matched with the parameter List<Customer>.
Change your server side method to something like:
[HttpPost]
public async Task<JsonResult> CreateCustomers(JObject queryParam)
{
// populate your list here
// for eaxample : var customers = queryParam["customers"].ToString();
}
And also you can use this code to send data to the server:
$http({
url: 'url',
dataType: 'json',
method: 'POST',
data: jsonData,
headers: { "Content-Type": "application/json" }
}).success(function(response){ $scope.response = response;
}).error(function(error){ $scope.error = error; });
I was quite confused with constructing data parameter of ajax using ASP.NET MVC and Webform and need an explanation from stackoverflow community.
First scenario (passing javascript object literal as data parameter in ajax using MVC) Results: It worked
MVC Controller
[HttpPost]
public JsonResult Register(string Name, string Birthday, int Gender)
{
.
.
.
return Json(message);
}
Javascript Code:
$.ajax({
url: "/Test/Register",
method: "POST",
dataType: "json",
data: {
Name:name,
Birthday:birthday,
Gender:gender
}
}).success(function (response) {
alert(response);
}).error(function (response) {
alert(response);
});
Second scenario (passing javascript object literal as a string as data parameter in ajax using MVC) Results: Cause error 500 (Internal Server Error)
Javascript Code:
var name = $('#Name').val();
var birthday = $('#Birthday').val();
var gender = $('#Gender').val();
var data = "{ Name:'" + name + "', Birthday:'" + birthday + "', Gender:'" + gender + "'}";
$.ajax({
url: "/Test/Register",
method: "POST",
dataType: "json",
data: data,
}).success(function (response) {
alert(response);
}).error(function (response) {
alert(response);
});
Results were different when I tested it on ASP.NET Webforms
Third scenario (passing javascript object literal as a string as data parameter in ajax using Webforms) Results: It worked
Webform WebMethod
[WebMethod]
public static string Submit(string Name, String Salary)
{
return "Success";
}
Javascript Code:
var name = $("#Name").val();
var salary = $("#Salary").val();
var data = "{ Name:'" + name + "', Salary:'" + salary + "'}";
$.ajax({
url: '/WebForm3.aspx/Submit',
contentType: "application/json; charset=utf-8",
method: 'POST',
data: data,
dataType: 'json',
success: function (response)
{
console.log(response);
},
error: function (response)
{
console.log(response);
}
});
Forth scenario (passing javascript object literal as data parameter in ajax using Webforms) Results: Cause error 500 (Internal Server Error)
$.ajax({
url: '/WebForm3.aspx/Submit',
contentType: "application/json; charset=utf-8",
method: 'POST',
data: {
Name: name,
Salary: salary
},
dataType: 'json',
success: function (response)
{
console.log(response);
},
error: function (response)
{
console.log(response);
}
});
Questions:
Why?
Will the scenarios that worked here on jQuery's ajax also work on other javascript frameworks like angularJS's $http service?
I also saw some scenarios on the internet that constructs its ajax data parameter using '=' example:
var reservation = { "CourseCode": courseCode.val().toString(), "Section": section.val().toString(), "DateFrom": dateF.toString(), "DateTo": dateT.toString(), "Schedule": reservations };
$.ajax({
url: '/ReserveSubject',
type: 'POST',
data: 'reservation=' + JSON.stringify(reservation),//Like this
Can anyone show more more ways to construct ajax data parameters aside from the scenarios above? It would also be much appreciated if someone could also show the most eloquent way of constructing data parameter.
No takers?
http://api.jquery.com/jquery.ajax/
documentation on jQuery's ajax data exerpts this:
data Type: PlainObject or String or Array Data to be sent to the
server. It is converted to a query string, if not already a string.
It's appended to the url for GET-requests. See processData option to
prevent this automatic processing. Object must be Key/Value pairs. If
value is an Array, jQuery serializes multiple values with same key
based on the value of the traditional setting (described below).
so you can pass it, string, aray or plain object,, while in Angulars data you can pass only string|object
https://docs.angularjs.org/api/ng/service/$http
so that's not same as in your examples,, you'll have to adjust if you send arrays
I suggest reducing the number of parameters on your controller actions to a single model object like:
public class RegisterModel
{
public string Name {get; set;}
public string Birthday {get; set;}
public int Gender {get; set;}
}
This is just good practice for clean code anyway.
And then in the client side you can have model builders which take the data you want to send and then send up this object instead of a bunch of parameters
I have an ajax call to a Controller on an ASP.NET MVC solution that looks like this:
$.ajax({
url: "ControllerClass/ControllerMethod?date=" + date,
type: "POST",
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (result) {
globalVariable = result; // This is for later...
DoSomething(result);
},
async: true,
processData: false
})
The controller once it has done all the work on the server side, it returns an Object which contains different property types (an Int, an Array of Int and a List of Objects)
The way that I return that data from the controller back to the JS file is...
return Json(new
{
summary = objectResult
});
The point is that from the JavaScript, now I would like to call a different Controller with the information that I have stored on my globalVariable which is defined in my JavaScript like this:
var globalVariable
That var located at the top of my JS file...
Well, the way I am trying to call back my controller with that variable looks like this:
$.ajax({
url: "ControllerClass/ControllerMethod?result=" + globalVariable,
type: "POST",
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (result) {
DoSomethingNewWithThisresult(result)
},
async: true,
processData: false
})
And this is my controller in C#.
public IActionResult ControllerMethod(JsonResult result)
{
DoSomethingHereWithTheResult(result);
}
Why if I put a breakpoing on my last controller, the result variable is empty? I checked on Chrome that the variable contains all the data that I am looking for. Actually, if I just pass one of the properties of the object, it goes to the controller just fine but I can't pass the whole Object...
Try to create your own custom Model instead of using JsonResult as parameter in the action and use it in ajax call this way:
$.ajax({
url: "ControllerClass/ControllerMethod",
type: "POST",
dataType: 'json',
data: { Summary: globalVariable.summary},
contentType: 'application/json; charset=utf-8',
success: function (result) {
DoSomethingNewWithThisresult(result)
}
})
public class YourClass
{
public string Summary { get; set;}//// string type or whatever it is
}
public IActionResult ControllerMethod(YourClass result)
{
DoSomethingHereWithTheResult(result);
}
alternatively you can also use JSON.stringify to serialize your object this way:
var customObject={
"Summary" : globalVariable.summary
};
$.ajax({
url: "ControllerClass/ControllerMethod",
type: "POST",
dataType: 'json',
data: JSON.stringify(customObject),
contentType: 'application/json; charset=utf-8',
success: function (result) {
DoSomethingNewWithThisresult(result)
}
})
Assuming this is a Web API controller, there are multiple ways to read a complex type from the URL - (there are also similar options to MVC controllers)
If the parameters are passed in the UrL, and assuming they map 1:1 to your object, you can decorate your object with the [FromUri] attribute, example:
public class GeoPoint
{
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public ValuesController : ApiController
{
public HttpResponseMessage Get([FromUri] GeoPoint location) { ... }
}
Another option which gives you more flexibility controlling the creation of your object and populating the parameters is by using the IModelBinder interface and [ModelBinder] attribute.
You can implement the IModelBinder interface with the only method "BindModel" to access the HTTP request just right before your Controller method is called, create your object, read the URL query params, set the values in your object then finally assign it to the Model property of the bindingContext:
A simple example would be like this:
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType == typeof(MyComplexType))
{
MyComplexType model ;
//You can use the value provider or get it from the HttpRequest
//var theValue = bindingContext.ValueProvider.GetValue ( bindingContext.ModelName);
//var theValue = request.RequestUri.ParseQueryString ( ) ;
if ( new MyComplexTypeConverter( ).TryParse ( actionContext.Request, out model) )
{
bindingContext.Model = model;
return true;
}
else
{
bindingContext.ModelState.AddModelError( bindingContext.ModelName, "Cannot convert request to MyComplexType");
return false;
}
}
return false ;
}
Here is a reference documentation: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
I'm trying to call an asmx web service method with jQuery and pass an actual JavaScript object for the data, and get JSON back. The closest I can come is this:
$.ajax({
url: "WebService.asmx/HelloWorld",
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ num: 12, name: "Adam" }),
dataType: "json",
success: function (data) { alert(data.d); }
});
How can I successfully make this call without first stringifying my object?
I tried this (removing the contentType)
$.ajax({
url: "WebService.asmx/HelloWorld",
type: "POST",
data: { num: 12, name: "Adam" },
dataType: "json",
success: function (data) { alert(data.d); }
});
But that returns the result in XML, not json.
Here's the web method:
[WebMethod]
[ScriptMethod]
public string HelloWorld(int num, string name) {
return ++num + name;
}
EDIT
Here's a screenshot of the headers of the request. Clearly content-type is set to xml for the response.
Set the ResponseFormat:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string HelloWorld(int num, string name) {
return ++num + name;
}
Just a NOTE: asmx doesn't return JSON for GETs only POST
Per Dave's Comments
It is impossible with the ASMX and ASPX JSON endpoints. They require the application/json Content-Type and a POST request or no JSON.