I am wanting to pass a dictionary of type <int,int> to my controller via an Ajax post.
The main reason here is the post may have between 1-3 key value pairs here (none of these values are known at compile time) and in the future it may go up to 5.
Also in the post I have to pass in some other data, such as Id and name, which all works as normal.
How would I construct this dictionay in the javascript then send it via the JQuery post and finally receive it on the controller to process?
Edit 2:
I have decided to just solve this with a post for each value instead of trying to pass a dictionary.
EDIT:
Here is my source for the function so you can see what I am trying:
function BindAddMenuItem() {
$(".AddMenuItem").click(function (e) {
e.preventDefault();
//get header id from link by removing addmenuitem from this.id
var currentId = $(this).attr("id").replace("AddMenuItem", "");
//get itemnumber, itemname, itemdetails from textboxes with same header id
var restaurantId = jQuery.trim($("#RestaurantId").val());
var itemNumber = jQuery.trim($("#ItemNumber" + currentId).val());
var itemName = jQuery.trim($("#ItemName" + currentId).val());
var itemDetails = jQuery.trim($("#ItemDetails" + currentId).val());
var costs = new Object();
//select all textboxes with class "Header" + currentId
$(".Header" + currentId).each(function (i) {
var optionId = $(this).attr("id").replace("Option", "");
costs[optionId] = $(this).val();
});
$.ajax(
{
type: "POST",
url: "/Menu/AddMenuItem",
data: "reastaurantId=" + restaurantId + "&menuHeaderId=" + currentId + "&itemNumber=" + itemNumber + "&itemName=" + itemName + "&itemDetails=" + itemDetails + "&costs=" + costs,
dataType: "html",
success: function (result) {
var domElement = $(result);
$("#MenuContainer").replaceWith(domElement);
var newNum = parseInt(itemNumber) + 1;
$("#ItemNumber" + currentId).val(newNum);
BindAllBehaviours();
}
});
});
}
Something like (javascript)
dict = new Object();
dict['12'] = 5;
dict['13'] = 6;
dict['1000'] = 21;
dict['9'] = 13;
dict['13'] = 48;
$.post('/client.mvc/mypostaction/', { myDictionary: dict });
You can then post the dict object to your controller using a Dictionary<int, int> as property type.
ActionResult MyPostAction(Dictionary<string, int> myDictionary)
edit from author's code second time:
The following works for me, when having a Dictionary<string, int> kvPairs. <int, int> isn't going to work after all.
Make your post like:
var dict = new Object();
dict['13'] = 9;
dict['14'] = 10;
dict['2'] = 5;
$.post('controller.mvc/Test', { 'kvPairs': dict }, function(obj) { $('#output').html(obj.Count); });
JavaScript object / dictionary has to be passed as a list of key-value pairs to ASP.NET MVC controller when Dictionary<TKey, TValue> is expected. Example:
If you have a dictionary like this:
public Dictionary<string, decimal?> SomeMapping { get; set; }
then you have to use something like this in your JavaScript:
var sourceMapping = { a: 1, b: 1.5, c: null };
var SomeMapping = [];
for (var key in sourceMapping) {
if (sourceMapping.hasOwnProperty(key)) {
SomeMapping.push({ Key: key, Value: sourceMapping[key] });
}
}
I've used this approach in asynchronous POST request (sent using jQuery) that had content type set to 'application/json' (this may or may not be important in your case).
Client (JavaScript):
var dict = new Object();
dict.Key1 = "Value1"
dict.Key2 = "Value2"
$.post('/YourController/YourAction/', dict);
NOTE: The "dict" objects gets serialized behind the scenes before being sent to your action.
Server:
public ActionResult YourAction()
{
string postData = string.Empty;
using (StreamReader sr = new StreamReader(Request.InputStream))
{
postData = sr.ReadToEnd();
}
//Load post data into JObject (Newtonsoft.Json)
JObject o = JObject.Parse(postData);
//Extract each key/val
string val1 = (string)o["Key1"];
//Do whatever....
}
None of these worked for me except for mczers, but he doesn't show all the steps, and makes it difficult when you're trying to remember how you set up an ajax request. So I wanted to put everything that actually just works. First, in JavaScript:
var validDict = new Array();
validDict[0] = { key: 1, value: 4 }
validDict[1] = { key: 42, value: 5}
var path = "#Url.Action("ControllerName", "ActionName")";
$.ajax({
url: path,
type: "POST",
data: JSON.stringify(validDict),
contentType: "application/json; charset=utf-8",
async:false,
success: function(status, xhr)
{
alert(status);
},
error: function(xhr, status, error)
{
alert(error);
}});
Then in your controller:
[HttpPost]
public ActionResult ActionName(Dictionary<int, int> validDict)
{
// doStuff();
return Content("Success");
}
A dictionary of the kind IDictionary<string, string> on server side can be posted from javascript like
{"Key1": "Value1", "Key2": "Value2"}
on the Server Side in ASP.NET Web API
[HttpPost]
public IHttpActionResult([FromBody]IDictionary<string, string> requestParam){
}
Above example is for an Http POST with the Json data in the Body
For passing a Dictionary I found the following working answer:
submitting-a-dictionary-to-an-asp-net-mvc-action
#model WebApplication3.Controllers.ExampleViewModel #{ ViewBag.Title = "New";
var first = Guid.NewGuid(); var second = Guid.NewGuid(); }
<h2>New</h2>
#using (Html.BeginForm(new { action = "create", controller = "home" })) {
foreach (var kvp in Model.Values) {
<p>
<input type="text" name="Model.Values[#first].Key" value="#kvp.Key" />
<input type="text" name="Model.Values[#first].Value" value="#kvp.Value" />
<input type="hidden" name="Model.Values.Index" value="#first" />
</p>
}
you have to generate A Guid for the dictionary index, and you have to create 3 inputs, one for the Key, one for the Value and one for the Index of the Dictionary
Also I have submited using Jquery with the following:
$('form#frmFormId').submit(function (e) {
e.preventDefault();
var formData = new FormData(this);
//debugger;
$('#cover-spin').show(100);
$.ajax({
type: 'POST',
url: $(this).attr('action'),
data: formData,
processData: false,
contentType: false
}
);
return false;
});
Related
Array of objects after stringifying is not passed to controller action and the parameter of action (the model) is null.
I have tried many solutions given to this problem in StackOverflow but none of these solution solved my problem. I provided the links which I tried:
Pass array to mvc Action via AJAX
pass array in javascript object to mvc controller
Here is my code
JavaScript Code
$("#FormSubmit").click(function () {
var datalist = [];
$("#MarksTable tbody tr").each(function () {
var obj = {};
obj.StudentID = 1;
obj.ExamTimeTableID = 1;
obj.ClassActivity = $(this).find("td:eq(5) input").val();
obj.IsPresent = $(this).find("td:eq(7) input").val();
obj.Assignment = $(this).find("td:eq(6) input").val();
obj.MidTerm = $(this).find("td:eq(3) input").val();
obj.Final = $(this).find("td:eq(4) input").val();
datalist.push(obj);
});
$.ajax({
url: "#Url.Action("InsertData", "Examination")",
type: "POST",
cache: false,
contentType: "application/json;charset=utf-8",
dataType: "json",
data: JSON.stringify(datalist),
success: function (result) {
alert(result);
},
error: function (errormessage) {
alert(errormessage.responseText);
}
});
});
Action of Controller:
[HttpPost]
public JsonResult InsertData([FromBody] List<StudentMarksList> obj)
{
DynamicParameters param = new DynamicParameters();
.
.
.
return Json(param.Get<string>("msg"));
}
The Model:
public class StudentMarksList
{
public int StudentID { get; set; }
public int ExamTimeTableID { get; set; }
public int ClassActivity { get; set; }
public int IsPresent { get; set; }
public int Assignment { get; set; }
public int MidTerm { get; set; }
public int Final { get; set; }
}
Request Payload:
[,…]
0: {StudentID: 1, ExamTimeTableID: 1, ClassActivity: 3, IsPresent: 0, Assignment: 2, MidTerm: 5, Final: 4}
Assignment: 2
ClassActivity: 3
ExamTimeTableID: 1
Final: 4
IsPresent: 0
MidTerm: 5
StudentID: 1
Request Payload source:
[{"StudentID":1,"ExamTimeTableID":1,"ClassActivity":3,"IsPresent":0,"Assignment":2,"MidTerm":5,"Final":4}]
The obj should contains the passed objects but it is null.
Any Help???
[Edit]
Change the js as below:
function toInt(str){
var i = parseInt(str);
return i ? i : 0;
}
$("#MarksTable tbody tr").each(function () {
var obj = {};
obj.StudentID = 1;
obj.ExamTimeTableID = 1;
obj.ClassActivity = toInt( $(this).find("td:eq(5) input").val());
obj.IsPresent =toInt( $(this).find("td:eq(7) input").val());
obj.Assignment = toInt( $(this).find("td:eq(6) input").val());
obj.MidTerm =toInt( $(this).find("td:eq(3) input").val());
obj.Final = toInt( $(this).find("td:eq(4) input").val());
datalist.push(obj);
});
This will make sure the empty input to 0 instead of null.
That's because on your server side you're declaring the ClassActivity/ClassActivity/Assignment/... as int type but your js send all them as string. For example, the Payload sent to server will be something like:
[{"StudentID":1,"ExamTimeTableID":1,"ClassActivity":"3","Assignment":"aa","MidTerm":"333333333","Final":"3333"},{"StudentID":1,"ExamTimeTableID":1,"ClassActivity":"","Assignment":"s","MidTerm":"2","Final":"1"},{"StudentID":1,"ExamTimeTableID":1,"ClassActivity":"3","Assignment":"","MidTerm":"2","Final":"1"}]
Please either change the property type or convert the $(this).find("td:eq(7) input").val() result (a string) to int/bool/... type before sending them.
You can try this also.
cshtml page you need to add one form tag like eg.
<div style="display:none;">
<form id="FormPost"></form>
</div>
Jquery Code
$("#FormSubmit").click(function () {
$("#FormPost").html('');
$("#MarksTable tbody tr").each(function (index,elem) {
addHidden("StudentID["+index+"]","1");
addHidden("ExamTimeTableID["+index+"]","1");
addHidden("ClassActivity["+index+"]",$(this).find("td:eq(5) input").val());
addHidden("IsPresent["+index+"]",$(this).find("td:eq(7) input").val());
addHidden("Assignment["+index+"]",$(this).find("td:eq(6) input").val());
addHidden("MidTerm["+index+"]",$(this).find("td:eq(3) input").val());
addHidden("Final["+index+"]",$(this).find("td:eq(4) input").val());
});
$.ajax({
url: "#Url.Action("InsertData", "Examination")",
type: "POST",
cache: false,
contentType: "application/json;charset=utf-8",
dataType: "json",
data: $("#FormPost").serialize(),
success: function (result) {
alert(result);
},
error: function (errormessage) {
alert(errormessage.responseText);
}
});
});
function addHidden(key, value) {
var input = document.createElement('input');
input.type = 'hidden';
input.name = key;
input.value = value;
$("#FormPost").appendChild(input);
}
Action of Controller:
[HttpPost]
public JsonResult InsertData(List<StudentMarksList> obj)
{
DynamicParameters param = new DynamicParameters();
.
.
.
return Json(param.Get<string>("msg"));
}
That could be dynamic value of one of property in object below is not a number, it contains some alphabet characters.
var obj = {};
obj.StudentID = 1;
obj.ExamTimeTableID = 1;
obj.ClassActivity = $(this).find("td:eq(5) input").val();//this value could be not a number, ex: 'abc' text
obj.IsPresent = $(this).find("td:eq(7) input").val();
obj.Assignment = $(this).find("td:eq(6) input").val();
obj.MidTerm = $(this).find("td:eq(3) input").val();
obj.Final = $(this).find("td:eq(4) input").val();
It will be reason that Asp.Net cannot deserialize your action parameter item to object of StudentMarksList.
If above is not the root cause, you can follow this question to log out serialization errors to have further investigation.
Simply add this property to your ajax call:
traditional:true,
such that your ajax call looks like this at the end
$.ajax({
url: "#Url.Action("InsertData", "Examination")",
type: "POST",
cache: false,
traditional:true,
contentType: "application/json;charset=utf-8",
dataType: "json",
data: JSON.stringify(datalist),
success: function (result) {
alert(result);
},
error: function (errormessage) {
alert(errormessage.responseText);
}
});
Happy coding. Hope it helps someone just as it helped me.
I've got working code in JQuery Ajax, however I've been told I have to use Native JS code to use it, and I'm not very familiar with using native JS for ajax, and most of the internet examples are basic ones. Basically, I have this object:
var Narudzba =
{
SifraNarudzbe: "AAA",
DatumNarudzbe: "",
Osigurano: document.getElementById("checkOsiguranje").value,
BrzaDostava: document.getElementById("checkBrza").value,
KlijentId: document.getElementById("klijentid").value,
Adresa: AdresaVar,
StatusNarudzbeID: 2,
Primaoc: PrimaocVar,
VrijemeIsporuke: null,
CijenaNarudzbe: UkupnaCijena,
NacinPlacanja: parseInt(document.getElementById("NacinPlacanja_Select").value)
};
Which I'm trying to post to my Controller. Here's how my working code in Jquery Ajax looks:
$.ajax({
url: "/klijentarea/klijent/SnimiNarudzbu",
data: Narudzba,
type: 'POST',
success: function (data) {
for (var i = 0; i < stavke_niz.length; i++) {
stavke_niz[i].NarudzbeId = parseInt(data);
}
stavke_niz = JSON.stringify(stavke_niz);
$.ajax({
url: "/klijentarea/klijent/SnimiStavke",
type: "POST",
dataType: "json",
data: stavke_niz,
contentType: 'application/json',
success: function (data) {
if (data === true) {
var id = document.getElementById("klijentid").value;
window.location.href = '/KlijentArea/Klijent?id=' + id;
}
}
});
}
});
Basically, it creates an order (Narudzba) with all sorts of details, posts it to this controller:
[HttpPost]
public int SnimiNarudzbu(Narudzbe Narudzba)
{
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var stringChars = new char[8];
var random = new Random();
for (int i = 0; i < stringChars.Length; i++)
{
stringChars[i] = chars[random.Next(chars.Length)];
}
var finalString = new String(stringChars);
Narudzba.SifraNarudzbe = finalString;
Narudzba.DatumNarudzbe = DateTime.Now;
ctx.Primaoci.Add(Narudzba.Primaoc);
ctx.Naruzbee.Add(Narudzba);
ctx.SaveChanges();
int newid = Narudzba.Id;
return newid;
}
Then I use the returned new ID, and assign it to all the objects inside stavke_niz, which is an array of order listings which gets created elsewhere in the code, and require OrderID before being added to database (I can add that code as well if necessary). Then the array with the updated OrderIDs gets sent to this controller:
[HttpPost]
public string SnimiStavke(IEnumerable<StavkaNarudzbe> stavke_niz)
{
if (stavke_niz != null)
{
ctx.StavkeNarudzbi.AddRange(stavke_niz);
ctx.SaveChanges();
return "true";
}
return "false";
}
Which successfully accepts the JSON posted with AJAX and adds the stuff to the database. Now, when I try to post in Native, like so:
var xhr = new XMLHttpRequest();
xhr.onload = function () {
if (xhr.status === 200 && this.readyState === 4)
{
alert(this.getAllResponseHeaders());
}
};
xhr.open('POST', '/klijentarea/klijent/SnimiNarudzbu', true);
xhr.send(Narudzba);
All of the values inside "Narudzba" are null, despite the object clearly having all the right values before being posted to controller. Help would be greatly appreciated.
You are missing Content-Type setting in your xhr request.
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
This should solve your problem.
Hope this helps!
I found some similar questions but none of them resolve my problem.
The problem I have is that my data from my AJAX-call is empty but my controller return exactly I want him to return.
I tried to add a contentType, but neither contentType nor ContentType worked for me.
What am I doing wrong?
JavaScript:
function AddFunction() {
var ergebnis = "";
var zahl1 = $("#txt_1").val();
var zahl2 = $("#txt_2").val();
$.ajax({
async: false,
cache: false,
type: 'POST',
url: '/Calc/Add',
dataType: 'JSON',
data: {
'val_1': zahl1,
'val_2': zahl2
},
success: function (data) {
ergebnis = data.result;
alert(ergebnis);
},
error: function () {
alert("Fehler");
}
});
}
Controller:
public ActionResult Add(string val_1, string val_2)
{
string sUri = "http://192.168.111.173:35145/temppath/GVCalc/1.0/add";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(sUri);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{\"field_1\":\"" + val_1 + "\"," +
"\"field_2\":\"" + val_2 + "\"}";
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
var result = DeserializeFromStream(httpResponse.GetResponseStream());
return Json(result);
}
Controller result:
{{
"result": 3
}}
Ajax data:
kinda empty / no result at all
Edit:
DeserializeFromStream Method:
public static object DeserializeFromStream(Stream stream)
{
var serializer = new JsonSerializer();
using (var sr = new StreamReader(stream))
using (var jsonTextReader = new JsonTextReader(sr))
{
return serializer.Deserialize(jsonTextReader);
}
}
I solved my problem by sending a string and parse it in JavaScript. This worked fine for me :)
C#:
return Json(result.ToString());
JavaScript:
var ergebnis_json = JSON.parse(data)
ergebnis = ergebnis_json.result;
$("#ergebnis").val(ergebnis);
Thanks everyone for their help :)
I have a Asp.net MVC program in which i want to get a list from the View using Javascript and pass that list to the controller. I want to the variables in the list to be string type except for one to be int32.
The problem is the list is either empty or does not pass.
I tried to use stringify but it doesn't fill the requirments.
Here is the code from the javascript part:
$('#AddColumn').click(function () {
var nodeURL = document.getElementById("IDHolder").innerHTML;
var nodeConfig= nodeURL+".CONFIG";
var nodeAdd=nodeURL+".CONFIG.AddColumn";
var nodeName = $("#ColumnName").val();
var nodeType = $("#ColumnType").data("kendoComboBox").value();
var ListNodedet = [nodeName, nodeType];
var Listmet = [nodeConfig, nodeAdd];
var ListNodeDetails = JSON.stringify(ListNodedet);
var ListMethod = JSON.stringify(Listmet);
var select = 1;
var url = "/Configuration/CallMethod";
$.get(url, { ListNodeDetails:ListNodeDetails, ListMethod:ListMethod }, function (data) {
$("#Data2").html(data);
});
})
The C# code for the controller were it calls another method in models:
public bool CallMethod(List<Variant> ListNodeDetails, List <string> ListMethod)
{
var AddMethod = RxMUaClient.CallMethod(ListNodeDetails, ListMethod, "127.0.0.1:48030");
return AddMethod;
}
The Model:
public static bool CallMethod(List<Variant> ListNodeDetails, List<string> ListMethod, string iPAddress)
{
var serverInstance = GetServerInstance(iPAddress);
if (serverInstance == null)
return false;
return serverInstance.CallMethod(ListNodeDetails, ListMethod);
}
The service model
public bool CallMethod(List<Variant> ListNodeDetails, List<string> ListMethod)
{
try
{
if (_mSession == null)
{
return false;
}
NodeId objectID = NodeId.Parse(ListMethod[0]);
NodeId Methodtype = NodeId.Parse(ListMethod[1]); ;
List<Variant> inputArguments = ListNodeDetails;
List<StatusCode> inputArgumentErrors = null;
List<Variant> outputArguments = null;
StatusCode error = _mSession.Call(
objectID,
Methodtype,
inputArguments,
new RequestSettings() { OperationTimeout = 10000 },
out inputArgumentErrors,
out outputArguments);
if (StatusCode.IsBad(error))
{
Console.Write("Server returned an error while calling method: " + error.ToString());
return false;
}
return true;
}
catch (Exception exception)
{
Console.WriteLine(exception.ToString());
return false;
}
}
At the end it calls some functions using OPC UA to add data.
I have changed it to be ajax function and it works well but only with one list form the lists passed to the method!
I dont know if this is because i read values from kendo box and text box, and they are different types but i tried to stringfy it and it still does not work. On the console both lists are out as strings. So still got a problem with passing the first List "ListNodeDetails"!
$('#AddColumn').click(function () {
var nodeURL = document.getElementById("IDHolder").innerHTML;
var nodeConfig= nodeURL+".CONFIG";
var nodeAdd=nodeURL+".CONFIG.AddColumn";
var nodeName = $("#ColumnName").val().toString();
var nodeType = $("#ColumnType").data("kendoComboBox").value().toString();
var ListNodedet = [nodeName, nodeType];
var Listmet = [nodeConfig, nodeAdd];
var params = {
ListNodeDetails: ListNodedet,
ListMethod: Listmet
};
var url = "/Configuration/CallMethod";
console.log(params); // added sanity check to make sure data is correctly passed
var temp = {
url: "/Configuration/CallMethod",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify(params),
success: function (params) {
window.location.replace(params.redirect);
}
};
$.ajax(temp);
})
I have a generic dispatcher that takes in parameters and then make $.ajax()
As you can see, I am looping through the parameters to build the data.
function dispatch(controller, action, param1, param2,...) {
var args = '', pg = 1, id = '';
var l = arguments.length;
var data = {};
for (var i = 2; i < arguments.length; i += 2) {
data[arguments[i]] = arguments[i + 1];
}
$.ajax({
type: "POST",
url: "/" + (controller + "/" + action,
data: data,
dataType: "json",
success: function (res) {
alert('success');
},
error: function (xhr, status, error) {
alert('error!');
}
});
}
This is how I call:
dispatch("XYZ", "AddGuests", "id", 10, "name", "Bob");
Everything works as expected and I get all parameters back in my MVC 3 controllers.
Now I need to pass multidimentional associative array as parameter to my controller.
I want to use the single generic dispatcher I use for other calls.
But somehow I am getting null for the associative array parameter.
Basically I want to post a guests array to my controller's List parameter.
Code to prepare the associative array data:
var guest = {};
var guests = [];
for(var i=0;i<2;i++){
var name = GetName();
var email = GetEmail();
guest = { 'Email': email, 'Name': name };
guests.push(guest);
}
End of the loop would give me, say:
{
{'Email':"bob#zyz.com", 'Name':"Bob"},
{'Email':"tom#zyz.com", 'Name':"Tom"}
}
This is the new call to the dispatcher:
dispatch("XYZ", "AddGuests", "id", 10, "guests", JSON.stringify(guests));
This is my controller:
[HttpPost]
public ActionResult AddGuests(string id, List<SelectedGuest> guests){
//save guests
}
[Serializable]
public class SelectedGuest
{
public string Email { get; set; }
public string Name { get; set; }
}
When I look at httpfox I see correct values posted:
id 10
guests [{"Email":"bob#zyz.com","Name":"Bob"},{"Email":"tom#zyz.com","Name":"Tom"}]
If I do this, I get the guest passed correctly to my controller:
But this limits me to pass just the guests array not other parameters.
data = JSON.stringify(guests);
What I am doing wrong? Thanks for reading.
If using JSON.stringify(guests) works, why not combine it into another JSON object with your other parameters that don't need stringification?
data = { "id": 10, "Guests": JSON.stringify(guests) };
Alternatively, you could construct a javascript object that combines these and call stringify on that.