I am facing problem while posting multiple objects via ajax jquery to MVC 4 controller. It has been weeks but I can't seem to find a solution.
I tried several approaches, sometimes the filterModel object is null and sometimes string parameters are null (doesn't matter even if I stringify of if I specify contentType or not)
What I want?
I want to pass three objects: 1. filterModel 2.testparamA 3.testparamB
What should I do to pass all three objects to MVC controller? What do I need to write in data: so I get all 3 object values?
The simplest Controller
[HttpPost]
public JsonResult Test(string testparamA, string testparamB, FilterModel filter)
{
using (RBSystemEntities repository = new RBSystemEntities())
{
return Json(new {
DataList = repository.Items.Select(x => new {x.PKID, x.ItemName}).ToList(),
Result = "OK"
});
}
}
The simplest View
var filterModel = #Html.Raw(Json.Encode(new FilterModel("ItemName", "Pepperoni Pizza")))
//filterModel = JSON.stringify(filterModel);
function testme() {
// post the javascript variable back to the controller
$.ajax({
url: '/Menu/Test',
type: 'POST',
//contentType: 'application/json; charset=utf-8',
data: {
filter: filterModel,
testparamA: 'A value',
testparamB: 'B value'
}, // with this approach I get filterModel null in the controller however testparamA and testparamB has values
data: filterModel, // with this approach I get values for filterModel but I can't pass testparamA and testparamB
success: function (result) {
// TODO: do something with the results
alert('success');
}
});
}
testme();
The simplest FilterModel class
public class FilterModel
{
public FilterModel() { }
public FilterModel(string filtercolumn, string filtervalue)
{
this.FilterColumn = filtercolumn;
this.FilterValue = filtervalue;
this.FilterColumnCriteria = "=";
}
public string FilterColumn { get; set; }
public string FilterValue { get; set; }
public string FilterColumnCriteria { get; set; }
}
Hope you don't mind me posting my comment (which was helpful) as an answer...
If you use stringify as follows it should work...
JSON.stringify({ fm: filterModel, ta: testparamA, tb: testparamA })
#PaulZahra guided me to the right direction.
Below changes fixed my problem:
contentType: 'application/json; charset=utf-8', // uncomment this
data: JSON.stringify({ filter: filterModel, testparamA: 'A value', testparamB: 'B value' }), //stringify whole thing and not just c# class
Related
I have two json array. I'm trying to send these json array to my controller. When i want to send one of them, everything is fine but i couldnt't send second one. How can i fix it ?
Post function from view
function HobiIlgiAlanKaydetGuncelle() {
var hobiler = $('#Hobiler').val(); // Json array of object
var ilgiAlanlar = $('#IlgiAlan').val();
$.ajax({
url: "/Kullanici/HobiVeIlgiAlanlariniKaydetGuncelle",
type: "POST",
contentType: 'application/json; charset=UTF-8',
dataType: 'json',
data: {hobiler : hobiler,ilgiAlanlar : ilgiAlanlar},
success: function (response) { }
});
}
Controller
[HttpPost]
public async Task<JsonResult> HobiVeIlgiAlanlariniKaydetGuncelle([FromBody] List<HobilerVM> hobiler, List<IlgiAlanlarVM> ilgiAlanlar)
{
//When I put second parameter, both of them comes with null
}
HobilerVM
public class HobilerVM
{
public int id { get; set; }
public string value { get; set; }
}
IlgiAlanVM
public class IlgiAlanVM
{
public int id { get; set; }
public string value { get; set; }
}
The issue is with the following line:
data: {hobiler : hobiler,ilgiAlanlar : ilgiAlanlar}
This is an object in javascript. The equivalent in c# should be:
public class MyData {
public List<HobilerVM> hobiler;
public List<IlgiAlanlarVM> ilgiAlanlar;
}
And then in your controller:
[HttpPost]
public async Task<JsonResult> HobiVeIlgiAlanlariniKaydetGuncelle([FromBody] MyData data)
{
//When i put second parameter, both of them comes with null
}
For more information, check Why does ASP.NET Web API allow only one parameter for POST method?
Web API doesn’t allow you to pass multiple complex objects in the
method signature of a Web API controller method — you can post only a
single value to a Web API action method. This value in turn can even
be a complex object. It is possible to pass multiple values though on
a POST or a PUT operation by mapping one parameter to the actual
content and the remaining ones via query strings.Reference: How to pass multiple parameters to Web API controller methods and How WebAPI does Parameter Binding
Solution
public class ComplexObject {
property List<HobilerVM> Hobiler { get; set; }
property List<IlgiAlanlarVM> IlgiAlanlar { get; set; }
}
[HttpPost]
public async Task<JsonResult> HobiVeIlgiAlanlariniKaydetGuncelle([FromBody] ComplexObject data)
{
//When i put second parameter, both of them comes with null
}
Happy coding, cheers!
I tried your code and it works fine for me except for some things.
First your second parameter has a different ViewModel on what you have posted on your code:
public class IlgiAlanVM
{
public int id { get; set; }
public string value { get; set; }
}
But on your parameter, you are using a different ViewModel:
([FromBody] List<HobilerVM> hobiler, List<IlgiAlanlarVM> ilgiAlanlar)
As you can see here, IlgiAlanVM is different on List<IlgiAlanlarVM>
Second, I just I used the same code but without the [FromBody]. So that would be:
//I already edited your List of Model here on the second parameter from IlgiAlanVM to IlgiAlanlarVM
[HttpPost]
public async Task<JsonResult> HobiVeIlgiAlanlariniKaydetGuncelle
(List<HobilerVM> hobiler, List<IlgiAlanlarVM> ilgiAlanlar)
Lastly, I just make sure it's an array of objects to make sure it will bind nicely on your list of models:
var hobiler = [{
id: 1,
value: 'My Value'
}];
var ilgiAlanlar = [{
id: 1,
value: 'MyValue'
}];
$.ajax({
url: '#Url.Action("HobiVeIlgiAlanlariniKaydetGuncelle", "Kullanici")',
type: "POST",
contentType: 'application/json; charset=UTF-8',
dataType: 'json',
data: JSON.stringify({ hobiler : hobiler, ilgiAlanlar : ilgiAlanlar }),
success: function (response) { }
});
Before I begin, I'd like to say - I realize that this question is very similar to many others that have been posted and answered on this site. I have read through and tried as many solutions as I could find that was related to my issue, and none have worked thus far.
I'm attempting to pass data from my web page to a controller method. The web page is very simple and only needs to capture information input by the user and send it off. I'm using Telerik's Kendo Grid to bind to and organize my data. No matter what I try, though, my AJAX post request never passes parameters forward correctly. When using my browser's debugger, I can see that the parameters being passed into the AJAX request are valid, but by the time they hit my breakpoint in the controller method, they are all either null or default.
Function Containing AJAX Request
function saveShiftDataToServer() {
var grid = $("#myGrid").data("kendoGrid");
var dataSource = grid.dataSource;
var allData = dataSource.data();
var comments = '#Model.Comments';
var loadInfoCorrect = '#Model.LoadInfoCorrect';
$.ajax({
type: "POST",
url: '/Home/SaveData',
data: JSON.stringify({ accessorials: allData, comments: comments, loadInfoCorrect: loadInfoCorrect }),
contentType: "application/json; charset=utf-8",
datatype: "json"
})
}
Controller Method
[AcceptVerbs("Post")]
public ActionResult SaveData(Accessorial[] accessorials, string comments, bool loadInfoCorrect)
{
// Code removed for brevity
}
My Kendo Grid is typed as Accessorial (the first controller method parameter type), so my assumption is that retrieving a collection of all present rows should return an array of that model. Even so, "comments" is a string, but is only ever passed to the controller method as null.
I'm new to ASP.NET Core and Kendo, so I'm sure there is something obvious that I'm missing. Any help would be appreciated!
I appreciate all of the responses! I was able to finally see valid data in my controller by changing the AJAX data type to "text" and simply passing the JSON directly for deserialization server-side. For some reason this is the only way that I've been able to make this work thus far.
AJAX POST Call
function saveShiftDataToServer() {
var grid = $("#accessorialGrid").data("kendoGrid");
var dataSource = grid.dataSource;
var allData = dataSource.data();
var shiftOverview = {
ShiftId: 0,
UserName: "test",
ShiftDate: null,
LoadList: null,
AccessorialList: allData,
LoadInfoCorrect: true,
Comments: ""
};
var jsonData = JSON.stringify(shiftOverview);
$.ajax({
type: "POST",
url: '/Home/SaveData',
data: { json: jsonData },
datatype: "text",
success: function (response) {
alert("111");
}
})
}
Controller Method
[AcceptVerbs("Post")]
public ActionResult SaveData(string json)
{
JsonConvert.DeserializeObject<ShiftOverview>(json); // This produces an object with valid data!
}
You could pass all your data in a ViewModel and get access to it using [FromBody] on action
public class ViewModel
{
public List<Accessorial> Accessorials{ get; set; }
public string Comments { get; set; }
public bool LoadInfoCorrect { get; set; }
}
Ajax:
var model = {};//pass all you data to an object
model.Accessorials = allData ;
model.comments = comments ;
model.loadInfoCorrect = loadInfoCorrect;
var items = JSON.stringify(model);
$.ajax({
url: '/GetAllCustDetails/SaveData',
type: "POST",
data: items,
contentType: 'application/json; charset=utf-8',
//dataType: "json",
success: function (response) {
alert("111");
}
});
Controller:
[HttpPost]
public ActionResult SaveData([FromBody]ViewModel model)
You are passing JSON object which corresponds to C# one like this:
public class Model {
public Accessorial[] Accessorials { get; set; }
public string Comments { get; set; }
public bool loadInfoCorrect { get; set; }
}
Try to declare such class above and adjust your action method this way:
public ActionResult SaveData(Model model)
{
// Code removed for brevity
}
If won't help - make model parameter object and check in debug mode what you are getting from AJAX call.
You juste have to use the [FromBody] attribute in your action method, like this :
[HttpPost]
public ActionResult SaveData([FromBody]Model model)
{
// Code removed for brevity
}
On my Client Side I have an ajax call like below:
$.ajax({
url: "Controller/ListResult",
type: 'POST',
contentType: "application/json;charset=utf-8",
data: JSON.stringify({
Id: ObjectId,
SessionKey: sessionManager.getSessionKey()
}),
dataType: "json",
success: function (result) {
var test = results;
}
}
});
In the Controller I have a method like this :
[HttpPost]
public JsonResult ListResult(string Id, string SessionKey)
{
IBl biz = new BL();
var result = biz.GetResults(Id,SessionKey);
return Json(result);
}
The problem is the result that controller returns is an object which has Enum properties (with their string representation as value). However when it reaches the success function in the ajax call, the enums are no longer string representation, and instead, they have been converted to their int values. How can I avoid this? and keep the string representation on the javascript side.
Instead of returning var result create some result entity class and you can mark the enum property there with StringEnumConverter.
class Result
{
[JsonConverter(typeof(StringEnumConverter))]
public EnumType EnumProperty { get; set; }
*****other properties goes here****
}
As Stephen suggested this works if one is using Json.NET as the serializer.
Try something like this:
var result = biz.GetResults(Id,SessionKey);
var modifiedResult = new
{
...,
r.EnumValue.ToString(),
...
};
return Json(modifiedResult);
I'm trying to make HTTP POST request to my C# controller, but I need to send in data an array, so I tried with JSON.stringify but when I start debugging, the input parameter in my controller is NULL?
I'm receiving a list from external API for weather forecast, so I need to create for each item in list new variable, that has some fields like : max and min temperature, description, humidity, pressure etc, and then of course fill these fields with data and add that variable to my array. Then I need to pass this array to my controller so I could store it in my database...
What type should I put in my controller so it would not be NULL? I'm totally new here so please help, any help is really more then welcome!
Below is code I have just to try :
var myData = { id:100, description:"some text"};
var myDataArray= new Array();
myDataArray.push(myData);
$.ajax({
dataType: "json",
type: "POST",
url: "/Weather1/Weather_post",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(myDataArray),
success: function (data) {
console.log(("OK"));
},
error: function (error)
{ console.log("NOT OK"); }
})
Controller:
[HttpPost]
public JsonResult Weather_post(String MyModuleList)
Model binding has no idea what "MyModuleList" is. You can use a strongly typed model here and MVC will bind the JSON to it.
Consider JSON:
var data = {
moduleList: [
{ id:100, description:"some text"}
];
};
and models:
public class ModuleListModel
{
public List<ModuleModel> ModuleList { get; set; }
}
public class ModuleModel
{
public int Id { get; set; }
public string Description { get; set; }
}
and action:
[HttpPost]
public JsonResult Weather_post(ModuleListModel model)
{
...
}
Combine that with #Timothy Shields' answer:
You're missing processData: false in your ajax call. Without that,
ajax is going to try to pack the data into the URL query string. (See
here: http://api.jquery.com/jQuery.ajax/)
and you should be good.
You're missing processData: false in your ajax call. Without that, ajax is going to try to pack the data into the URL query string. (See here: http://api.jquery.com/jQuery.ajax/)
If data is { 'animal': 'elephant', 'count': 5 } and processData is true (the default), ajax will do the POST to the URL /Weather1/Weather_post?animal=elephant&count=5 with an empty HTTP request body. This is why you want processData: false.
Try as follows:
var myData = { id:100, description:"some text"};
var myDataArray= new Array();
myDataArray.push(myData);
var param = JSON.stringify(myDataArray);
$.ajax({
dataType: "json",
type: "POST",
url: "/Weather1/Weather_post",
contentType: "application/json; charset=utf-8",
data: {'MyModuleList': param },
success: function (data) {
console.log(("OK"));
},
error: function (error)
{ console.log("NOT OK"); }
})
You may need to pass the parameter name with the data. Something like:
data: {'MyModuleList': JSON.stringify(myDataArray)},
See if this works for you.
I have a json object like this:
var itemData = {
"translations":[
{
"value":"Byron",
"languageId":1
},
{
"value":"hgfdfghds",
"languageId":3
}
],
"itemId":204,
"itemCategoryId":44
};
And I POST it using jQuery like this:
$.ajax({
url: "items/update",
dataType: "json",
type: "POST",
data: itemData,
});
When the call arrives at my ASP.NET MVC4 controller action, the non-list properties are assigned. However, the translations array only has two empty objects (instantiated, but with null/default property values). Here is my controller action method and my models:
public JsonResult Update(UpdateItemModel model)
{
if(model.Translations[0].Value!="Byron")
{
throw new Exception("That translation's value should have been populated with 'Byron'.");
}
return Json("ok");
}
public class UpdateItemModel
{
public List<TranslationModel> Translations { get; set; }
public int ItemId { get; set; }
public int ItemCategoryId { get; set; }
}
public class TranslationModel
{
public string Value { get; set; }
public int LanguageId { get; set; }
}
If I look at Request.Form in the immediate window, I can see that the translations "array" is encoded for some reason (maybe that's correct, not sure). If I try Request.Form["translations"] I get null. Here's an example of the raw form data that I'm seeing:
{translations%5b0%5d%5bvalue%5d=Byron&translations%5b0%5d%5blanguageId%5d=1&translations%5b1%5d%5bvalue%5d=hgfdfghds&translations%5b1%5d%5blanguageId%5d=3&itemId=204&itemCategoryId=44}
Not sure if my problem has anything to do with the "encoding" of the json at the beginning of that string. I looked at it in Fiddler and saw the same thing, so I can't blame ASP.NET for tampering.
What could be the problem here?
You should specify the content type (json) and stringify it using JSON.stringify
$.ajax({
url: "items/update",
dataType: "json",
contentType: "application/json; charset=utf-8;",
type: "POST",
data: itemData,
data: JSON.stringify(itemData),
});
Another thing to do is use add a JsonValueProviderFactory:
ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
in Application_Start method in Global.asax
This article might help you.
When you pass data for Ajax call is good to specify the content and stringfy the data:
$.ajax({
/*More stuff*/
data: JSON.stringify(itemData),
contentType: 'application/json',
dataType: "json",
type: "POST"
});
Then the value provider and the default ModelBinder will do the job.
I can see the json object properties are not matching .net properties, In json you have "value" in .net "Value" case is different. Try making the case to march the .net model