C# 将 JSON 数组发布到 mvc 控制器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13779043/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 09:46:49  来源:igfitidea点击:

Post JSON array to mvc controller

c#asp.net-mvcarraysjsonpost

提问by Yustme

I'm trying to post a JSON array to an MVC controller. But no matter what I try, everything is 0 or null.

我正在尝试将 JSON 数组发布到 MVC 控制器。但无论我尝试什么,一切都是 0 或 null。

I have this table that contains textboxes. I need from all those textboxes it's ID and value as an object.

我有一张包含文本框的表格。我需要从所有这些文本框中将它的 ID 和值作为一个对象。

This is my Javascript:

这是我的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;
    });
});

This is my view code:

这是我的视图代码:

<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>

This is the controller im trying to receive the data to:

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

[HttpPost]
public ActionResult Update(CustomTypeModel ctm)
{


   return RedirectToAction("Index");
}

What am I doing wrong?

我究竟做错了什么?

采纳答案by Darin Dimitrov

There are lots of issues with your code. Let's start with the markup. You have a table and inside each row of this table you are including hidden fields. Except that you have hardcoded the idattribute of those hidden elements meaning that you could potentially end up with multiple elements with the same id in your markup which results in invalid markup.

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

So let's start by fixing your markup first:

因此,让我们首先修复您的标记:

@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>
}

Alright, now you have valid markup. Now let's move on to the javascript event which will be triggered when some submitTestbutton is clicked. If this is the submit button of the form I would recommend you subscribing to the .submitevent of the form instead of the .clickevent of its submit button. The reason for this is because a form could be submitted for example if the user presses the Enter key while the focus is inside some input field. In this case your click event won't be triggered.

好的,现在您有了有效的标记。现在让我们继续讨论submitTest单击某个按钮时将触发的 javascript 事件。如果这是表单的提交按钮,我建议您订阅.submit表单的.click事件而不是其提交按钮的事件。这样做的原因是因为例如如果用户在焦点位于某个输入字段内时按下 Enter 键,则可以提交表单。在这种情况下,您的点击事件不会被触发。

So:

所以:

$(document).ready(function () {
    $('form').submit(function () {
        // code to follow

        return false;
    });
});

Alright, next comes the part where you need to harvest the values of the hidden elements which are inside the table and put them into a javascript object that we will subsequently JSON serialize and send as part of the AJAX request to the server.

好的,接下来是您需要收集表内隐藏元素的值并将它们放入一个 javascript 对象的部分,我们随后将 JSON 序列化并作为 AJAX 请求的一部分发送到服务器。

Let's go ahead:

让我们继续:

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()
    });
});

So far we've filled our parameters, let's send them to the server now:

到目前为止,我们已经填写了我们的参数,让我们现在将它们发送到服务器:

$.ajax({
    url: this.action,
    type: this.method,
    data: JSON.stringify(parameters),
    contentType: 'application/json; charset=utf-8',
    success: function (result) {
        // ...
    },
    error: function (request) { 
        // ...
    }
});

Now let's move on to the server side. As always we start by defining a view model:

现在让我们转到服务器端。和往常一样,我们首先定义一个视图模型:

public class MyViewModel
{
    public string TransID { get; set; }
    public string ItemID { get; set; }
    public string TypeID { get; set; }
}

and a controller action that will take a collection of this model:

和一个控制器动作,它将采取这个模型的集合:

[HttpPost]
public ActionResult Update(IList<MyViewModel> model)
{
    ...
}

And here's the final client side code:

这是最终的客户端代码:

$(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;
    });
});

Obviously if your view model is different (you haven't shown it in your question) you might need to adapt the code so that it matches your structure, otherwise the default model binder won't be able to deserialize the JSON back.

显然,如果您的视图模型不同(您没有在问题中显示它),您可能需要调整代码以使其与您的结构相匹配,否则默认模型绑定器将无法反序列化 JSON。

回答by Ph0en1x

I think you doing thing's in a bit wrong manner for MVC world. If you have a proper model for binding your data with - you better using helpers going from the box instead of using "handmade" JavaScript. Take a look to HtmlHelper or AjaxHelper if you need async calls.

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

And bind you data to model using @Html.TextBoxFor()notation inside @Html.BeginFormblock That will simplify your code much and reduce amount of javascript, which is much better for maintenance.

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

On the server part you need to implement custom model binder and change settings to make handle request for current controller action via your model binder. It will take you to write some serverside code, but statically typed code looks easier to code and test or me, and it's better suit or your application needs, because I prefer JavaScript doing things it should do = > managing UI, but not constructing model for correct parsing on the serverside. It's better suit for single responsibility principle.

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

See this video, this is simple tutorial how to do that

看这个视频,这是一个简单的教程如何做到这一点

回答by Amin Saqi

There is another simpler way: using Query String to send your data. If you got intrested, your current approach is wrong because the JSON array data type is stringnot CustomTypeModel.

还有另一种更简单的方法:使用查询字符串发送数据。如果您感兴趣,那么您当前的方法是错误的,因为 JSON 数组数据类型string不是CustomTypeModel.

First of all, remove the dataajax option. We don't need that anymore.

首先,删除dataajax选项。我们不再需要那个了。

Second, change your controller like the following:

其次,更改您的控制器,如下所示:

[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");
}

Note1: It's important that names of your CustomTypeModelproperties be the same as what you enter as the JSON elements. So, your CustomTypeModelshould be like this:

注意 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; }
}

Note2: This approach is useful when you want to send the data through query strings. So, your url can be like this:

注意 2:当您想通过查询字符串发送数据时,此方法很有用。所以,你的网址可以是这样的:

url: '/controller/action?json=' + JSON.stringify(trans)