如何将字段值作为列表传递到模型绑定

how do i pass field values to my model binding as a list

提问人:bvsta 提问时间:11/5/2023 更新时间:11/5/2023 访问量:43

问:

我正在使用以下脚本在表单中的卡片中动态添加和删除字段。我正在尝试将值传递给我的模型绑定属性,该属性是一个List<ushort>

    <div style="width:40%;">
                <div class="">
                    <div class="col-lg-12">
                        <div id="row">
                            <div class="input-group m-3">
                                <div class="input-group-prepend">
                                    <button class="btn btn-danger"
                                            id="DeleteRow"
                                            type="button">
                                        <i class="bi bi-trash"></i>
                                        Delete
                                    </button>
                                </div>
                                <input type="text" class="form-control m-input">
                            </div>
                        </div>

                        <div id="newinput"></div>
                        <button id="rowAdder" type="button" class="btn btn-dark">
                            <span class="bi bi-plus-square-dotted">
                            </span> ADD
                        </button>
                    </div>
                </div>
</div>
<script type="text/javascript">
            $("#rowAdder").click(function () {
                    newRowAdd =
                        '<div id="row"> <div class="input-group m-3">' +
                        '<div class="input-group-prepend">' +
                        '<button class="btn btn-danger" id="DeleteRow" type="button">' +
                        '<i class="bi bi-trash"></i> Delete</button> </div>' +
                        '<input type="text" class="form-control m-input"> </div> </div>';

                    $('#newinput').append(newRowAdd);
                });
                $("body").on("click", "#DeleteRow", function () {
                    $(this).parents("#row").remove();
                })
</script>

我尝试使用绑定到模型属性的隐藏字段,并在提交到数组时更新该字段。

  function updatePortsInput() {
      console.log("updatePortsInput called");
      var ports = [];
      $(".m-input").each(function () {
          var portValue = parseInt($(this).val());
          if (!isNaN(portValue) && portValue >= 0 && portValue <= 65535) {
              ports.push(portValue);
          }
      });

      $('[name="Ports"]').val(JSON.stringify(ports));
  }

 <input type="hidden" id="portsInput" name="Ports" asp-for="Ports" />

但是我无法使用生成的字段的值填充我的列表。

有人对此有想法吗?

JavaScript C# asp.net Razor

评论


答:

1赞 BenderBoy 11/5/2023 #1

您在请求中混合了表单和 json 内容。您没有显示您发送请求的确切方式,但看起来您正在提交表单。默认情况下,这将发送 类型的内容,因此请求正文将如下所示(格式化):application/x-www-form-urlencoded

ports: "[1,2,3,4,5,6,7]"
__RequestVerificationToken: "CfDJ8KVrOUsD…"

框架现在会将处理程序参数与请求中的值(字符串)进行匹配。它不知道字符串是json数组,所以会无法解析成指定的类型。portsList<ushort>

你必须决定:

  1. 继续发送混合内容并在后端手动解析 Json
  2. 发送表单请求正文
  3. 发送 Json 请求正文

选项 1:自行解析 Json

保持一切原样,但在页面处理程序上,更改为 然后调用它。List<ushort> portsstring portsJsonSerializer.Deserialize<List<ushort>>(ports)

如果您有其他输入要与相同的请求一起发送,并且您希望框架以通常的方式处理它们,这可能会很有趣。但实际上,我更喜欢选项 2。

选项 2:发送表单内容

给你所有的输入命名,删除Json的东西,提交表格,它就可以工作了。ports

<form asp-page-handler="Form" method="POST">
    <input name="ports" type="number" value="1"/>
    <input name="ports" type="number" value="2"/>
    <input name="ports" type="number" value="3"/>
    <button type="submit">Submit</button>
</form>
public IActionResult OnPostForm(List<ushort> ports)
{
    foreach (var port in ports)
        Console.WriteLine(port);
    return RedirectToPage();
}

就做这个。

选项 3:发送 Json 内容

不要将 Json 数组放在隐藏的表单输入中。相反,将其放入请求正文中,并将请求内容类型声明为 .告诉页面处理程序从请求正文中获取参数。框架将神奇地为您解析 json:application/json

<form asp-page-handler="Json" onsubmit="go(event)">
    <input class=".m-input" type="number" value="1" />
    <input class=".m-input" type="number" value="2" />
    <input class=".m-input" type="number" value="3" />
    <button type="submit">Submit</button>
</form>

<script>
    $(".m-input").each(function () {
        var portValue = parseInt($(this).val());
        if (!isNaN(portValue) && portValue >= 0 && portValue <= 65535) {
            ports.push(portValue);
        }
    });

    //above is the code that collects your inputs into an array,
    //which i copied from you.
    //below is a vanilla javascript fetch request that sends this
    //array as json. You can probably do that with jQuery, too,
    //but I don’t know how.

    async function go(e) {
        e.preventDefault();
        fetch('@Url.Page("", "Json")', {
            method: 'POST',
            headers: new Headers({ 'content-type': 'application/json' }),
            body: JSON.stringify(ports),
        });
    }
</script>
public IActionResult OnPostJson([FromBody] List<ushort> ports)
{
    foreach (var port in ports)
        Console.WriteLine(port);
    return new JsonResult("thx i enjoyed those ports");
}

与其他选项相比,这将发送异步请求,即浏览器不会导航。

因为你是用javascript自己构建请求的,所以 ASP.NET Core可能随表单生成的CSRF令牌不会自动发送,所以你需要弄清楚这一点(你可以在标头中发送它,或者让你的后端忽略它)。

评论

1赞 bvsta 11/5/2023
解释得很好,非常感谢。我会调查并做出决定。