【问题标题】:Post JSON array to mvc controller将 JSON 数组发布到 mvc 控制器
【发布时间】:2012-11-26 13:45:27
【问题描述】:

我正在尝试将 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;
    });
});

这是我的视图代码:

<table>
        <tr>
            <th>trans</th>
            <th>Item</th>
            <th>Type</th>
        </tr>

        @foreach (var t in Model.Types.ToList())
        {
            {
            <tr>
                <td>                  
                    <input type="hidden" value="@t.TransID" id="TransID" />
                    <input type="hidden" value="@t.ItemID" id="ItemID" />
                    <input type="hidden" value="@t.TypeID" id="TypeID" />
                </td>
            </tr>
           }
        }
</table>

这是我试图接收数据的控制器:

[HttpPost]
public ActionResult Update(CustomTypeModel ctm)
{


   return RedirectToAction("Index");
}

我做错了什么?

【问题讨论】:

  • 请展示您的CustomTypeModel 的样子。
  • 你使用的是哪个版本的mvc?
  • 似乎您可能缺少 name 属性以及您尝试发布的属性的名称。你能发布你发布的实际数据吗?实际的 POST 请求?
  • @DarinDimitrov,您的答案中的 CustomTypeModel 部分正确。我忘了发布那个代码。但重要的是你有它。

标签: c# asp.net-mvc arrays json post


【解决方案1】:

您的代码存在很多问题。让我们从标记开始。您有一个表格,并且在该表格的每一行中都包含隐藏字段。除了您对这些隐藏元素的 id 属性进行了硬编码,这意味着您可能最终会在标记中使用多个具有相同 id 的元素,从而导致标记无效。

所以让我们先修复你的标记:

@foreach (var t in Model.Types.ToList())
{
    <tr>
        <td>                  
            <input type="hidden" value="@t.TransID" name="TransID" />
            <input type="hidden" value="@t.ItemID" name="ItemID" />
            <input type="hidden" value="@t.TypeID" name="TypeID" />
        </td>
    </tr>
}

好的,现在您有了有效的标记。现在让我们继续讨论当单击某个submitTest 按钮时将触发的javascript 事件。如果这是表单的提交按钮,我建议您订阅表单的.submit 事件,而不是其提交按钮的.click 事件。这样做的原因是因为可以提交表单,例如,如果用户在焦点位于某个输入字段内时按下 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<MyViewModel> 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 .

【讨论】:

  • 当我遇到类似问题时,我的 C# 模型类缺少 ` { get;放; } ` 为其每个属性。
【解决方案2】:

还有另一种更简单的方法:使用查询字符串发送数据。如果你有兴趣, 您当前的方法是错误的,因为 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<CustomTypeModel> ctm = 
         new JavaScriptSerializer().Deserialize<IList<CustomTypeModel>>(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: '/controller/action?json=' + JSON.stringify(trans)

【讨论】:

    【解决方案3】:

    我认为你在 MVC 世界中做事的方式有点错误。 如果你有一个合适的模型来绑定你的数据——你最好使用从盒子里出来的助手,而不是使用“手工制作的”JavaScript。如果您需要异步调用,请查看 HtmlHelper 或 AjaxHelper。

    并使用@Html.BeginForm 块内的@Html.TextBoxFor() 表示法将您的数据绑定到模型这将大大简化您的代码并减少javascript 的数量,这对于维护来说要好得多。

    在服务器部分,您需要实现自定义模型绑定器并更改设置以通过模型绑定器处理当前控制器操作的请求。它会带你编写一些服务器端代码,但是静态类型的代码看起来更容易编码和测试或者我,它更适合你的应用程序需要,因为我更喜欢 JavaScript 做它应该做的事情 => 管理 UI,但不构建模型在服务器端正确解析。它更适合单一责任原则。

    查看video,这是如何做到这一点的简单教程

    【讨论】:

    • 它是一个复杂的类型。不能像那样被束缚,至少我还没弄清楚怎么做。 javascript 现在对我有用。但是为了记录,没有@Html.InputFor()
    • 感谢 InputFor,我上次编写 java 代码,很难正确记住所有名称。我编辑了我的答案,你可以看看它。
    • 听起来不错,但我已经尝试了很多方法来避免使用 javascript。这是一个复杂的模型。另外,我确实使用了@Html.TextBoxFor(),但我不知道如何使用 javascript 从中获取数据。
    • 该函数中的第二个参数是对象,它是具有 html 属性的简单 POCO 及其值。你可以写@Html.TextBoxFor(m =&gt; m.SomeValue, new {id="myControl"})之类的东西,然后通过像一个简单的输入这样的id从javascript中查询它。
    • 啊我不知道可以那样做。这样可以使代码更具可读性,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2012-04-17
    • 2016-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-22
    • 2012-10-03
    • 1970-01-01
    相关资源
    最近更新 更多