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) { }
});
Related
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
}
I am using JSGrid to allow me to modify data. I am trying to setup the updateItem as follows:
updateItem: function (item) {
return $.ajax({
type: "PUT",
url: "/api/data/" + item.logID,
data: item,
contentType: "application/json;charset=utf-8",
dataType: "json"
});
}
I have a model as follows:
public class LogEntry
{
public string firstName { get; set; }
public string lastName { get; set; }
public string comment { get; set; }
public bool modified { get; set; }
public DateTime inTime { get; set; }
public DateTime outTime { get; set; }
public double totalHrs { get; set; }
public int logID { get; set; }
}
Here is my ApiController Class that contains the Put method:
public class DataController : ApiController
{
public void Put(int id, [FromBody]LogEntry item)
{
if(item != null)
{
//DO STUFF
}
}
}
However no matter what I do the item is always Null. I have tried the following:
Change to [FromBody]JObject item
Change to [FromBody]String item
Change the data: field to Json.Stringify
Change to [FromBody]String to just String
Add and remove context type of application/json;charset=utf-8 to the updateItem ajax call.
I have used Fiddler to see the data sent back. It shows the correct JSON being sent but the Put method doesn't seem to be getting that data.
Any ideas on what might be causing this behavior would be great. I have been researching around but nothing has worked yet.
Resolution Notes
It turned out that both answers from Caz1224 and CodeFuller aided in fixing this. CodeFuller's way of finding the error message lead me to the JSON coming back to the server. It was messed up even though Fiddler said it was correct. I changed my Ajax call to stringify the item. Which then matched my Model exactly.
return $.ajax({
type: "PUT",
url: "/api/data/" + item.logID,
data: JSON.stringify(item),
contentType: "application/json; charset=utf-8",
dataType: "json"
FromBody attribute is not strictly required here because non-simple types are built by the default from the request body.
I don't see any problems with your code so far, it should work for valid request. Seems like the problem is with the request sent and it causes model binding error. To proceed with the analysis check the following:
Check the value of ActionContext.ModelState.IsValid in Put() method. Is it true or false?
If it's false, check collection ActionContext.ModelState.Values in debugger. It should contain model binding errors that will hint you were the problem actually happens.
I had this issue and its painful!!
This is what ended up working for me.
The first part is my javascript (I guess that is how you are making your JSON)
"List" is my array that PERFECTLY matches (Even to the case, it matters) to my C# model.
Javascript Build List
var List = [];
$.each(_questions, function () {
var limitID = this.id.substr(-1);
var Quest = $('#Quest_' + ID).val();
var objectpush = {
LimitID: limitID,
Quest: Quest,
ID: ID
}
List.push(objectpush);
Then in the AJAX call further on I specify data like so:
data: JSON.stringify(List),
And finally this is on my C# API
public JsonResult QueryLimits(int UserID, [FromBody] List<List> List)
Hope this helps get you on the track. Don't just copy the code as I changed the name to List throughout my code and that will cause issues!
Caz
I have the following code in my jQuery file
var bases = {};
for (var j = 0; j < selectedVariants.length; j++) {
bases[selectedVariants[j].BId] = selectedVariants[j].CId;
}
and i am getting some data in bases dictionary now
and my question here is how do I pass this bases dictionary to controller through ajax call.
I tried the following thing but bases count in the controller is coming as ZERO
$.ajax({
url: $.url('~/TUP/Tflow'),
type: 'POST',
data: { baseDetails: JSON.stringify(bases)},
async: true,
cache: false,
});
Here when I see in my controller ... bases count is coming as ZERO
Please help me on this
Controller :
[HttpPost]
public JsonResult Tflow(JsonFileContentInputs basedetails)
{
//some code
}
and my model :
[ModelBinder(typeof(JsonModelBinder))]
[DataContract]
public class JsonFileContentInputs
{
[JsonProperty(PropertyName = "basedetails")]
[DataMember]
public Dictionary<string, string> basedetails { get; set; }
}
Try the following approach. As #EhsanSajjad mentioned, you'll need to call JSON.stringify on all of your data, not just the bases object:
$.ajax({
url: '/TUP/Tflow',
type: 'POST',
data: "json=" + JSON.stringify({baseDetails: bases}), // stringify everything,
dataType: 'text',
async: true,
cache: false
});
Then in your controller, instead of trying to use model binding, we can just deserialize the data ourselves using Json.NET.
Controller:
[HttpPost]
public ActionResult Tflow(string json)
{
// deserialize
var data = JsonConvert.DeserializeObject<JsonFileContentInputs>(json);
// more code
}
Model:
// You can drop these two as we aren't using the modelbinding
// [ModelBinder(typeof(JsonModelBinder))]
// [DataContract]
public class JsonFileContentInputs
{
[JsonProperty(PropertyName = "baseDetails")]
public Dictionary<string, string> BaseDetails { get; set; }
}
Unfortunately, reading the raw stream of the request in the controller seems to be necessary as MVC controllers won't play nice with raw JSON by default. More info here.
EDIT: It looks like you can pass raw JSON to an MVC controller, you just need to specify the ajax dataType as text and ensure the parameter names match up. I've updated my answer accordingly.
Instead of receiving the Class object, you should receive it as string and then serialize into object like below.
public JsonResult Tflow(string basedetails)
{
//some code
var model = new JavascriptSerializer().Deserialize<JsonFileContentInputs>(basedetails);
// Your code
}
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
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