可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am creating a small app to teach myself ASP.NET MVC and JQuery, and one of the pages is a list of items in which some can be selected. Then I would like to press a button and send a List (or something equivalent) to my controller containing the ids of the items that were selected, using JQuery\'s Post function.
I managed to get an array with the ids of the elements that were selected, and now I want to post that. One way I could do this is to have a dummy form in my page, with a hidden value, and then set the hidden value with the selected items, and post that form; this looks crufty, though.
Is there a cleaner way to achieve this, by sending the array directly to the controller? I\'ve tried a few different things but it looks like the controller can\'t map the data it\'s receiving. Here\'s the code so far:
function generateList(selectedValues) {
var s = {
values: selectedValues //selectedValues is an array of string
};
$.post(\"/Home/GenerateList\", $.toJSON(s), function() { alert(\"back\") }, \"json\");
}
And then my Controller looks like this
public ActionResult GenerateList(List<string> values)
{
//do something
}
All I managed to get is a \"null\" in the controller parameter...
Any tips?
回答1:
I modified my response to include the code for a test app I did.
Update: I have updated the jQuery to set the \'traditional\' setting to true so this will work again (per @DustinDavis\' answer).
First the javascript:
function test()
{
var stringArray = new Array();
stringArray[0] = \"item1\";
stringArray[1] = \"item2\";
stringArray[2] = \"item3\";
var postData = { values: stringArray };
$.ajax({
type: \"POST\",
url: \"/Home/SaveList\",
data: postData,
success: function(data){
alert(data.Result);
},
dataType: \"json\",
traditional: true
});
}
And here\'s the code in my controller class:
public JsonResult SaveList(List<String> values)
{
return Json(new { Result = String.Format(\"Fist item in list: \'{0}\'\", values[0]) });
}
When I call that javascript function, I get an alert saying \"First item in list: \'item1\'\". Hope this helps!
回答2:
FYI: JQuery changed the way they serialize post data.
http://forum.jquery.com/topic/nested-param-serialization
You have to set the \'Traditional\' setting to true, other wise
{ Values : [\"1\", \"2\", \"3\"] }
will come out as
Values[]=1&Values[]=2&Values[]=3
instead of
Values=1&Values=2&Values=3
回答3:
Thanks everyone for the answers. Another quick solution will be to use jQuery.param method with traditional parameter set to true to convert JSON object to string:
$.post(\"/your/url\", $.param(yourJsonObject,true));
回答4:
Don\'t post the data as an array. To bind to a list, the key/value pairs should be submitted with the same value for each key.
You should not need a form to do this. You just need a list of key/value pairs, which you can include in the call to $.post.
回答5:
In .NET4.5
, MVC 5
Javascript:
object in JS:
mechanism that does post.
$(\'.button-green-large\').click(function() {
$.ajax({
url: \'Quote\',
type: \"POST\",
dataType: \"json\",
data: JSON.stringify(document.selectedProduct),
contentType: \'application/json; charset=utf-8\',
});
});
C#
Objects:
public class WillsQuoteViewModel
{
public string Product { get; set; }
public List<ClaimedFee> ClaimedFees { get; set; }
}
public partial class ClaimedFee //Generated by EF6
{
public long Id { get; set; }
public long JourneyId { get; set; }
public string Title { get; set; }
public decimal Net { get; set; }
public decimal Vat { get; set; }
public string Type { get; set; }
public virtual Journey Journey { get; set; }
}
Controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Quote(WillsQuoteViewModel data)
{
....
}
Object received:
Hope this saves you some time.
回答6:
Another implementation that is also working with list of objects, not just strings:
JS:
var postData = {};
postData[values] = selectedValues ;
$.ajax({
url: \"/Home/SaveList\",
type: \"POST\",
data: JSON.stringify(postData),
dataType: \"json\",
contentType: \"application/json; charset=utf-8\",
success: function(data){
alert(data.Result);
}
});
Assuming that \'selectedValues\' is Array of Objects.
In the controller the parameter is a list of corresponding ViewModels.
public JsonResult SaveList(List<ViewModel> values)
{
return Json(new {
Result = String.Format(\"Fist item in list: \'{0}\'\", values[0].Name)
});
}
回答7:
As I discussed here ,
if you want to pass custom JSON object to MVC action then you can use this solution, it works like a charm.
public string GetData()
{
// InputStream contains the JSON object you\'ve sent
String jsonString = new StreamReader(this.Request.InputStream).ReadToEnd();
// Deserialize it to a dictionary
var dic =
Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<String, dynamic>>(jsonString);
string result = \"\";
result += dic[\"firstname\"] + dic[\"lastname\"];
// You can even cast your object to their original type because of \'dynamic\' keyword
result += \", Age: \" + (int)dic[\"age\"];
if ((bool)dic[\"married\"])
result += \", Married\";
return result;
}
The real benefit of this solution is that you don\'t require to define a new class for each combination of arguments and beside that, you can cast your objects to their original types easily.
and you can use a helper method like this to facilitate your job
public static Dictionary<string, dynamic> GetDic(HttpRequestBase request)
{
String jsonString = new StreamReader(request.InputStream).ReadToEnd();
return Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(jsonString);
}
回答8:
You can setup global parameter with
jQuery.ajaxSettings.traditional = true;
回答9:
The answer helped me a lot in my situation so thanks for that.
However for future reference people should bind to a model and then validate. This post from Phil Haack describes this for MVC 2. http://haacked.com/archive/2010/04/15/sending-json-to-an-asp-net-mvc-action-method-argument.aspx
Hope this helps someone.