POST 表单数组没有成功 [英] POST a form array without successful

查看:43
本文介绍了POST 表单数组没有成功的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 C# 和 .NET Framework 4.5.1 开发 ASP.NET MVC 5 网站.

我在 cshtml 文件中有这个 form:

@model MyProduct.Web.API.Models.ConnectBatchProductViewModel@{布局 = 空;}<!DOCTYPE html><头><meta name="viewport" content="width=device-width"/><title>创建</title><身体>@if (@Model != null){<h4>产品:@Model.Product.ProductCode,候选人:@Model.ExternalCodesForThisProduct</h4>使用 (Html.BeginForm("Save", "ConnectBatchProduct", FormMethod.Post)){@Html.HiddenFor(model => model.Product.Id, new { @id = "productId", @Name = "productId" });<div><table id ="batchTable" class="order-list"><头><tr><td>Cantidad</td><td>洛特</td></tr></thead><tr><td>@Html.TextBox("ConnectBatchProductViewModel.BatchProducts[0].Quantity")</td><td>@Html.TextBox("ConnectBatchProductViewModel.BatchProducts[0].BatchName")</td><td><a class="deleteRow"></a></td></tr></tbody><脚><tr><td colspan="5" style="text-align: left;"><input type="button" id="addrow" value="添加行"/></td></tr></tfoot>

<p><input type="submit" value="Seleccionar"/></p>}}别的{<div>错误.</div>}<script src="~/Scripts/jquery-2.1.3.min.js"></script><script src="~/js/createBatches.js"></script><!-- 资源 jQuery -->

这是动作方法:

[HttpPost]公共 ActionResult 保存(FormCollection 表单){返回空;}

还有两个ViewModel:

公共类 BatchProductViewModel{公共整数数量{得到;放;}公共字符串 BatchName { get;放;}}公共类 ConnectBatchProductViewModel{公共模型.产品产品{得到;放;}公共 int ExternalCodesForThisProduct { 获取;放;}公共 IEnumerable批量产品 { 获取;放;}}

但我在 FormCollection 表单 var 中得到了这个:

但我想得到一个 IEnumerable模型:

public ActionResult Save(int productId, IEnumerable模型);

如果我使用上面的方法签名,两个参数都是空的.

我想要一个 IEnumerable 因为用户将使用 jQuery 动态添加更多行.

这是 jQuery 脚本:

jQuery(document).ready(function ($) {无功计数器 = 0;$("#addrow").on("click", function () {counter = $('#batchTable tr').length - 2;var newRow = $("");var cols = "";var数量 = 'ConnectBatchProductViewModel.BatchProducts[0].Quantity'.replace(/[.{1}]/, '[' + counter + ']');var batchName = 'ConnectBatchProductViewModel.BatchProducts[0].BatchName'.replace(/[.{1}]/, '[' + counter + ']');cols += '<td><input type="text" name="' + 数量 + '"/></td>';cols += '<td><input type="text" name="' + batchName + '"/></td>';cols += '<td><input type="button" class="ibtnDel" value="Delete"></td>';newRow.append(cols);$("table.order-list").append(newRow);计数器++;});$("table.order-list").on("click", ".ibtnDel", function (event) {$(this).closest("tr").remove();计数器 -= 1$('#addrow').attr('disabled', false).prop('value', "Add Row");});});

有什么想法吗?

我已经检查了这个 SO 答案,以及 这篇文章 但我的代码无法正常工作.

解决方案

您需要在 for 循环中为集合生成控件,以便使用索引器正确命名它们(注意属性 BatchProducts 需要是 IList

@using (Html.BeginForm("Save", "ConnectBatchProduct", FormMethod.Post)){....<表格>....@for(int i = 0; i ....}

那么POST方法需要

public ActionResult Save(ConnectBatchProductViewModel 模型){....}

编辑

注意:除了您的编辑之外,如果您想在视图中动态添加和删除 BatchProductViewModel 项目,您将需要使用 BeginCollectionItem 帮助程序或 html 模板如这个答案

动态添加新项目的模板是

注意虚拟索引器和隐藏输入的不匹配值会阻止此模板回发.

然后添加一个新的BatchProducts的脚本是

$("#addrow").click(function() {var index = (new Date()).getTime();//唯一索引器var clone = $('#NewBatchProduct').clone();//克隆 BatchProducts 项//更新克隆的索引clone.html($(clone).html().replace(/[#]/g, '[' + index + ']'));clone.html($(clone).html().replace(/"%"/g, '"' + index + '"'));$("table.order-list").append(clone.html());});

I'm developing an ASP.NET MVC 5 web with C# and .NET Framework 4.5.1.

I have this form in a cshtml file:

@model MyProduct.Web.API.Models.ConnectBatchProductViewModel

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Create</title>
</head>
<body>
    @if (@Model != null)
    { 
        <h4>Producto: @Model.Product.ProductCode, Cantidad: @Model.ExternalCodesForThisProduct</h4>
        using (Html.BeginForm("Save", "ConnectBatchProduct", FormMethod.Post))
        {
            @Html.HiddenFor(model => model.Product.Id, new { @id = "productId", @Name = "productId" });

            <div>
                <table id ="batchTable" class="order-list">
                    <thead>
                        <tr>
                            <td>Cantidad</td>
                            <td>Lote</td>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>@Html.TextBox("ConnectBatchProductViewModel.BatchProducts[0].Quantity")</td>
                            <td>@Html.TextBox("ConnectBatchProductViewModel.BatchProducts[0].BatchName")</td>
                            <td><a class="deleteRow"></a></td>
                        </tr>
                    </tbody>
                    <tfoot>
                        <tr>
                            <td colspan="5" style="text-align: left;">
                                <input type="button" id="addrow" value="Add Row" />
                            </td>
                        </tr>
                    </tfoot>
                </table>
            </div>
            <p><input type="submit" value="Seleccionar" /></p>
        }
    }
    else
    { 
        <div>Error.</div>
    }
<script src="~/Scripts/jquery-2.1.3.min.js"></script>
<script src="~/js/createBatches.js"></script> <!-- Resource jQuery -->    
</body>
</html>

And this is the action method:

[HttpPost]
public ActionResult Save(FormCollection form)
{
    return null;
}

And the two ViewModel:

public class BatchProductViewModel
{
    public int Quantity { get; set; }
    public string BatchName { get; set; }
}

public class ConnectBatchProductViewModel
{
    public Models.Products Product { get; set; }
    public int ExternalCodesForThisProduct { get; set; }

    public IEnumerable<BatchProductViewModel> BatchProducts { get; set; }
}

But I get this in FormCollection form var:

But I want to get an IEnumerable<BatchProductViewModel> model:

public ActionResult Save(int productId, IEnumerable<BatchProductViewModel> model);

If I use the above method signature both parameters are null.

I want an IEnumerable because user is going to add more rows dynamically using jQuery.

This is jQuery script:

jQuery(document).ready(function ($) {
    var counter = 0;

    $("#addrow").on("click", function () {

        counter = $('#batchTable tr').length - 2;

        var newRow = $("<tr>");
        var cols = "";

        var quantity = 'ConnectBatchProductViewModel.BatchProducts[0].Quantity'.replace(/[.{1}]/, '[' + counter + ']');
        var batchName = 'ConnectBatchProductViewModel.BatchProducts[0].BatchName'.replace(/[.{1}]/, '[' + counter + ']');

        cols += '<td><input type="text" name="' + quantity + '"/></td>';
        cols += '<td><input type="text" name="' + batchName + '"/></td>';

        cols += '<td><input type="button" class="ibtnDel"  value="Delete"></td>';
        newRow.append(cols);

        $("table.order-list").append(newRow);
        counter++;
    });


    $("table.order-list").on("click", ".ibtnDel", function (event) {
        $(this).closest("tr").remove();

        counter -= 1
        $('#addrow').attr('disabled', false).prop('value', "Add Row");
    });
});

Any idea?

I have checked this SO answer, and this article but I don't get my code working.

解决方案

You need to generate the controls for the collection in a for loop so they are correctly named with indexers (note that property BatchProducts needs to be IList<BatchProductViewModel>

@using (Html.BeginForm("Save", "ConnectBatchProduct", FormMethod.Post))
{
  ....
  <table>
    ....
    @for(int i = 0; i < Model.BatchProducts.Count; i++)
    {
      <tr>
        <td>@Html.TextBoxFor(m => m.BatchProducts[i].Quantity)</td>
        <td>@Html.TextBoxFor(m => m.BatchProducts[i].BatchName)</td>
        <td>
          // add the following to allow for dynamically deleting items in the view
          <input type="hidden" name="BatchProducts.Index" value="@i" />
          <a class="deleteRow"></a>
        </td>
      </tr>
    }
    ....
  </table>
  ....
}

Then the POST method needs to be

public ActionResult Save(ConnectBatchProductViewModel model)
{
  ....
}

Edit

Note: Further to your edit, if you want to dynamically add and remove BatchProductViewModel items in he view, you will need to use the BeginCollectionItem helper or a html template as discussed in this answer

The template to dynamically add new items would be

<div id="NewBatchProduct" style="display:none">
  <tr>
    <td><input type="text" name="BatchProducts[#].Quantity" value /></td>
    <td><input type="text" name="BatchProducts[#].BatchName" value /></td>
    <td>
      <input type="hidden" name="BatchProducts.Index" value ="%"/>
      <a class="deleteRow"></a>
    </td>
  </tr>
</div>

Note the dummy indexers and the non-matching value for the hidden input prevents this template posting back.

Then the script to add a new BatchProducts would be

$("#addrow").click(function() {
  var index = (new Date()).getTime(); // unique indexer
  var clone = $('#NewBatchProduct').clone(); // clone the BatchProducts item
  // Update the index of the clone
  clone.html($(clone).html().replace(/[#]/g, '[' + index + ']'));
  clone.html($(clone).html().replace(/"%"/g, '"' + index  + '"'));
  $("table.order-list").append(clone.html());
});

这篇关于POST 表单数组没有成功的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆