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
I know this has been asked a lot of times. But believe me I have tried them and this ain't working.
I have this simple List and Method :-
$scope.TblData = [];
var Name='Name'; var Desc='Desc';
$scope.TblData = [
{ Key: Name, Value: ClassSubjectName },
{ Key: Desc, Value: ClassSubjectDesc }
];
InsertFactory.InsertClassSubject($scope.TblData).then(function (d) {
alert(d.data + ' Subject Details');
}, function (error) {
alert('Cannot Save Contact Details');
})
Which I'm getting at factory like :-
BoardObj.InsertClassSubject = function (TblData) {
var ViewID = 'ClassSubject';
var Data = $.param({ TblList: ViewID, TblData: TblData });
return $http({
method: 'POST',
url: '/Admin/InsertTblData',
data: JSON.stringify(Data),
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"
}
});
}
Trying to get it at server like this:-
if (Request.Form["TblData"] != null)
{
JsonData = Request.Form["TblData"].ToString();
}
aBundleInsert.TblDataParams = JsonConvert.DeserializeObject<List<KeyValuePair<string, string>>>(JsonData);
Ofcourse I'm doing it wrong but can't find the issue.
You are not posting your data as form post.
TblData is a scope variable, it will not come inside your Form object, Form is meant for input elements only.
Ideally you should be posting the data to a model at the server side, but if you still want to access it on server side, you can try like following.
string postContent = "";
HttpContext.Current.Request.InputStream.Position = 0;
using (var reader = new StreamReader(Request.InputStream,
System.Text.Encoding.UTF8, true, 4096, true))
{
if (HttpContext.Current.Request.ContentLength > 0)
{
postContent = reader.ReadToEnd();
}
}
I'm trying to use AJAX and calling web method like this in my code.
function generate_source(year_source, month_source) {
var gData_source = '';
if (year_source) {
gData_source = [];
gData_source[0] = year_source;
gData_source[1] = month_source;
console.log('first part');
}
else {
var d_source = new Date();
gData_source = [];
gData_source[0] = d_source.getFullYear();
gData_source[1] = d_source.getMonth() + 1;
console.log('second part');
}
var jsonData_source = JSON.stringify({
gData_source: gData_source
});
var ctx = document.getElementById("order_source").getContext('2d');
$.ajax({
url: "dashboard.aspx/getordersource",
data: jsonData_source,
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
beforeSend: function () {
$("#loader_divsource").show();
},
success: function (response) {
$("#loader_divsource").hide();
var chartLabel = eval(response.d[0]); //Labels
var chartData = eval(response.d[1]); //Data
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: chartLabel,
datasets: [
{
type: 'doughnut',
label: chartLabel,
data: chartData,
backgroundColor: [
"#FF6384",
"#36A2EB",
],
hoverBackgroundColor: [
"#FF6384",
"#36A2EB",
]
}
]
}
});
}
});
}
var d_source = new Date();
gData_source = [];
$('#year_source').val(d.getFullYear());
$('#month_source').val(d.getMonth() + 1);
generate_source('', '');
My web method is like this;
[System.Web.Services.WebMethod]
public static List<string> getordersource(List<int> gData)
{
DataSet ds = ws_db.get_Dataset_order_source();
var returnData = new List<string>();
......
return returnData;
}
Whenever I try to run this data, my breakpoint for the web method is not hit. Further, if i use the same method without data, i don't get this error. It's driving me crazy.
I think your problem is in this code :
var jsonData_source = JSON.stringify({
gData_source: gData_source
});
you are trying to serialize array with key value pair that it is become invalid.
change to this :
var jsonData_source = JSON.stringify(gData_source);
also your web method should be like this :
[System.Web.Services.WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.JSON)]
// just return a string, not list, your JSON string should have contain all your enumerable in your string Data
public static string getordersource(List<int> gData)
{
DataSet ds = ws_db.get_Dataset_order_source();
JsonSerializer serializer = new JsonSerializer();
var returnData = serializer.serialize(ds);
......
return returnData;
}
Hope it helps.
I have a model I am trying to pass in from my view to my controller via an Ajax call which stringifies both the model and another string of data like this:
SetBinConfig: function (model, range) {
var _model = JSON.stringify(model);
var rangeSplit = range.split(/[ -]+/);
var _rangeSplit = JSON.stringify(rangeSplit);
var data = "model=" +_model + "&rangeSplit=" + _rangeSplit;
$.ajax({
url: '/IdentifiConfig/DefaultConfiguration/SetBinConfiguration',
type: 'POST',
data: "{'data' : '" + data + "'}",
dataType: 'json',
contentType: 'application/json; charset=utf-8',
cache: false,
success: function (data) {
if (data.error == 1) {
cc.jqUtils.openDialog(data.ErrorDescription, 'Error', 'OK', null, null, null);
}
},
error: function (x, h, r) {
console.log(x, h, r);
}
});
},
Which is then received by this method:
public ActionResult SetBinConfiguration(string data)
{
string range = data.Split(new string[] { "&rangeSplit=" }, StringSplitOptions.RemoveEmptyEntries)[1];
string tempModelData = data.Split(new string[] {"&rangeSplit="}, StringSplitOptions.RemoveEmptyEntries)[0];
string modelData = tempModelData.Replace("model=", "");
DefaultConfigurationModel model = new JavaScriptSerializer().Deserialize<DefaultConfigurationModel>(modelData);
string[] rangeSplit = Regex.Split(range, " - ");
foreach (IdentifiBINConfiguration ibc in model.IdentifiBINConfigs)
{
if (ibc.LowerRange == rangeSplit[0] && ibc.UpperRange == rangeSplit[1])
{
model.IdentifiBINConfiguration = ibc;
return Json(new { error = 0 });
}
}
return Json(new { error = 1 });
}
However, I get this error:
The value "System.Collections.Generic.Dictionary`2[System.String,System.Object]" is not of type "IdentifiMessenger.Implementations.Identifi.Object.IdentifiBINConfiguration" and cannot be used in this generic collection. Parameter name: value
And I don't know what that means at all. I know what the Dictionary is, but why can I not just deserialize this object? I followed other answers right here on SO and I don't understand why this isn't working.
Edit:
Model is quite literally my model, sent from my JS like this:
IdentifiConfig.SetBinConfig(#Html.Raw(Json.Encode(Model)), $('#BinRangesHidden').val());
And range is just a value from a hidden. I'm not posting back my model because I just need to modify one value and then have the page pull that modified value down later.
You still have to serialize your data.
data: JSON.stringify(data),
Then in your controller, your object should auto-parse:
public ActionResult SetBinConfiguration(MyData data)
Alternatively, you can parse it manually:
public ActionResult SetBinConfiguration(string data)
{
MyData resumeDto = JsonConvert.DeserializeObject<MyData>(data);
...
I call an action method via AJAX and return a list object, I am having difficulty in de-serializing the response in JQuery. I try to iterate through the repsone via $.each function but I get NULL. I know for sure data returned contains an object.
[HttpPost]
public JsonResult ToolTips(string viewName)
{
List<ToolTipMvc.Models.ToolTipMvcModel> result = ToolTipMvc.Models.ToolTipMvcModel.GetToolTip(viewName);
var y = result;
JavaScriptSerializer jss = new JavaScriptSerializer();
string output = jss.Serialize(result);
return Json(output);
}
public static List<ToolTipMvcModel> GetToolTip(string viewName)
{
List<ToolTipMvcModel> items = new List<ToolTipMvcModel>();
//items.AddRange(toolTipIds.Select(s => GetToolTip(s)));
ToolTip tp = new ToolTip();
ToolTipMvcModel item = new ToolTipMvcModel();
item.Description = "list item 1";
item.Field = "ctrlOne";
ToolTipMvcModel item2 = new ToolTipMvcModel();
item.Description = "list item 2";
item.Field = "ctrlTwo";
items.Add(item);
return items;
}
$.ajax({
type: 'POST',
url: toolTipsUrl,
cache: false,
datatype: "html",
data: { viewname: "runCreate" },
success: function (data) {
alert(data);
data = JSON.parse(data);
alert(data);
$.each(data, function (dt) {
var mydata = data.Field;
alert(mydata);
});
}
EDIT
When I alert the data I see the JSON being returned for instance
[{"Field: "ctrlTwo", "Description":"List item 2"},{"Field: "ctrlTwo", "Description":"List item 2"}]
but when I use JSON.Parse(data) or $.parseJson(data) I see object object. I just want interate through and populate some text areas on the page
First of all, there is no need to explicitly use the JavaScriptSerializer yourself. The call to Json will serialize it for you, so instead have your controller method look like this:
[HttpPost]
public JsonResult ToolTips(string viewName)
{
List<ToolTipMvc.Models.ToolTipMvcModel> result = ToolTipMvc.Models.ToolTipMvcModel.GetToolTip(viewName);
return Json(result);
}
Doing this also means that you shouldn't need to perform any explicit JSON.Parse or $.parseJson.
In your success handler, you should be able to iterate through the results as follows:
success: function(data) {
for (var i = 0; i < data.length; i++) {
var item = data[i];
console.log(item.Description);
console.log(item.Field);
}
}
I read here some topics how to get properties values from an object.
In my case, I have something in Controller:
[HttpPost]
public ActionResult GetSomething() {
return Json( new {
data = AModel.Get()
}, JsonRequestBehavior.AllowGet );
}
In model:
public static List<Hashtable> Get() {
List<Hashtable> list = new List<Hashtable>( 0 );
Hashtable table = new Hashtable();
table.Add( "ITEM_1", "Value1" );
table.Add( "ITEM_2", "Value 32" );
list.Add( table );
table = new Hashtable();
table.Add( "ITEM_1", "Value22" );
table.Add( "ITEM_2", "Other" );
list.Add( table );
return list;
}
And in Javascript:
var test;
$.ajax({
type: "post",
url: "Action/Controller",
data: {},
dataType: "json",
async: false,
success: function (data) {
test = data.data;
},
complete: function () {
console.log(test);
});
I got in console like in the following image:
I want to get the value of property ITEM_1 and results to me : Value1, Value22.
I tried with
for(var key in test) {
console.log(test[key].ITEM_1);
//console.log(test[key].ITEM1);
}
but it not works.
Of course, I renamed ITEM_1 key into ITEM1 (in model) but same result : undefined but in console I see the values for all object.
Help me please.
test is an array and not an object. loop through the array like:
var testLength = test.length; //caching length, performance benefit
i, item1;
for(i=0;i<testLength;i++){
item1 = test[i].Properties.ITEM1;
}