将JSON数组发布到mvc控制器
我正在尝试将JSON数组发布到MVC控制器。 但无论我尝试什么,一切都是0或null。
我有这个包含文本框的表。 我需要从所有这些文本框中将ID和值作为对象。
这是我的Javascript:
$(document).ready(function () { $('#submitTest').click(function (e) { var $form = $('form'); var trans = new Array(); var parameters = { TransIDs: $("#TransID").val(), ItemIDs: $("#ItemID").val(), TypeIDs: $("#TypeID").val(), }; trans.push(parameters); if ($form.valid()) { $.ajax( { url: $form.attr('action'), type: $form.attr('method'), data: JSON.stringify(parameters), dataType: "json", contentType: "application/json; charset=utf-8", success: function (result) { $('#result').text(result.redirectTo) if (result.Success == true) { return fase; } else { $('#Error').html(result.Html); } }, error: function (request) { alert(request.statusText) } }); } e.preventDefault(); return false; }); });
这是我的观看代码:
trans Item Type @foreach (var t in Model.Types.ToList()) { { } }
这是我试图接收数据的控制器:
[HttpPost] public ActionResult Update(CustomTypeModel ctm) { return RedirectToAction("Index"); }
我究竟做错了什么?
您的代码存在很多问题。 让我们从标记开始。 你有一张桌子,在这张桌子的每一行里面你都有隐藏的字段。 除非您已经对这些隐藏元素的id
属性进行了硬编码,这意味着您可能最终会在标记中找到具有相同ID的多个元素,从而导致无效标记。
所以让我们首先修复你的标记:
@foreach (var t in Model.Types.ToList()) { }
好的,现在你有了有效的标记。 现在让我们转到javascript事件,当点击某个submitTest
按钮时将触发该事件。 如果这是表单的提交按钮,我建议您订阅表单的.submit
事件而不是其提交按钮的.submit
事件。 这样做的原因是,例如,如果用户在焦点位于某个输入字段内时按下Enter键,则可以提交表单。 在这种情况下,您的点击事件不会被触发。
所以:
$(document).ready(function () { $('form').submit(function () { // code to follow return false; }); });
好的,接下来是你需要收集表中隐藏元素的值并将它们放入javascript对象的部分,我们随后将JSON序列化并作为AJAX请求的一部分发送到服务器。
让我们继续:
var parameters = []; // TODO: maybe you want to assign an unique id to your table element $('table tr').each(function() { var td = $('td', this); parameters.push({ transId: $('input[name="TransID"]', td).val(), itemId: $('input[name="ItemID"]', td).val(), typeId: $('input[name="TypeID"]', td).val() }); });
到目前为止,我们已经填充了参数,现在让它们发送到服务器:
$.ajax({ url: this.action, type: this.method, data: JSON.stringify(parameters), contentType: 'application/json; charset=utf-8', success: function (result) { // ... }, error: function (request) { // ... } });
现在让我们转到服务器端。 我们一如既往地定义视图模型:
public class MyViewModel { public string TransID { get; set; } public string ItemID { get; set; } public string TypeID { get; set; } }
以及将采用此模型集合的控制器操作:
[HttpPost] public ActionResult Update(IList model) { ... }
这是最终的客户端代码:
$(function() { $('form').submit(function () { if ($(this).valid()) { var parameters = []; // TODO: maybe you want to assign an unique id to your table element $('table tr').each(function() { var td = $('td', this); parameters.push({ transId: $('input[name="TransID"]', td).val(), itemId: $('input[name="ItemID"]', td).val(), typeId: $('input[name="TypeID"]', td).val() }); }); $.ajax({ url: this.action, type: this.method, data: JSON.stringify(parameters), contentType: 'application/json; charset=utf-8', success: function (result) { // ... }, error: function (request) { // ... } }); } return false; }); });
显然,如果您的视图模型不同(您没有在问题中显示它),您可能需要调整代码以使其与您的结构匹配,否则默认模型绑定器将无法反序列化JSON。
还有一种更简单的方法:使用Query String发送数据。 如果您有兴趣,那么您当前的方法是错误的,因为JSON数组数据类型是string
而不是CustomTypeModel
。
首先,删除data
ajax选项。 我们不再那样了。
其次,更改您的控制器,如下所示:
[HttpPost] public ActionResult Update(string json) { // this line convert the json to a list of your type, exactly what you want. IList ctm = new JavaScriptSerializer().Deserialize>(json); return RedirectToAction("Index"); }
注意1: CustomTypeModel
属性的名称与您作为JSON元素输入的名称相同很重要。 所以,你的CustomTypeModel
应该是这样的:
public class CustomTypeModel { // int, or maybe string ... whatever you want. public int TransIDs { get; set; } public int ItemIDs { get; set; } public int TypeIDs { get; set; } }
注意2:当您想通过查询字符串发送数据时,此方法很有用。 所以,你的url可以是这样的:
url: '/controller/action?json=' + JSON.stringify(trans)
我认为你为MVC世界做了一些有点错误的事情。 如果你有一个合适的模型来绑定你的数据 – 你最好使用从盒子里拿出的帮助,而不是使用“手工”的JavaScript。 如果需要异步调用,请查看HtmlHelper或AjaxHelper。
并使用@Html.TextBoxFor()
@Html.BeginForm
块中的@Html.TextBoxFor()
表示法将数据绑定到模型。这将简化您的代码并减少javascript的数量,这对于维护来说要好得多。
在服务器部分,您需要实现自定义模型绑定器并更改设置,以通过模型绑定器对当前控制器操作进行处理请求。 你需要编写一些服务器端代码,但是静态类型代码看起来更容易编码和测试,或者它更适合你的应用程序需求,因为我更喜欢JavaScript应该做的事情=>管理UI,但不是构建模型在服务器端正确解析。 它更适合单一责任原则。
看到这个video ,这是一个简单的教程如何做到这一点