【问题标题】:Id being posted is always the Id from first row of table发布的 ID 始终是表格第一行的 ID
【发布时间】:2017-03-24 05:50:34
【问题描述】:

MVC 5 项目。使用模态视图。模态有 2 个部分。顶部是一个带有“添加”按钮的下拉列表。下面是主表,具有行删除功能(如下所述)。它应该如何工作:如果用户单击“添加”,则条目将进入表中。这工作正常。我正在尝试让特定于行的删除功能现在正常工作。让我描述一下这个问题......

我基本上有一个包含许多项目的表格,每行都有一个删除按钮。行是这样创建的...

<table class="table table-striped">
    <tr>
        <th>
           @Html.DisplayNameFor(model => model.Filter.Filter1)
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
      {
         <tr>
            <td>
               @Html.DisplayFor(modelItem => item.Filter.Filter1)
            </td>
         <td>
         @using (Html.BeginForm("DeleteFromModal", "carColorsFilters", FormMethod.Post))
            {
                <b>@item.Id</b>
                @Html.Hidden("id", item.Id)
                @Html.Hidden("carColorId", (Int32)ViewBag.carColorId)
                <input class="btn btn-primary" type="submit" value="Delete" />
            }
          </td>
        </tr>
    }
</table>

我的帖子操作被定义为...

        public ActionResult DeleteFromModal(int id, int carColorId)
    {
        carColorsFilter carColorsFilter = db.carColorsFilters.Find(id);
        db.carColorsFilters.Remove(carColorsFilter);
        db.SaveChanges();


        ViewBag.carColorId = carColorId;
        ViewBag.FilterId = new SelectList(db.Filters, "Id", "Filter1");
        var carColorsfilters = db.carColorsFilters
                .Where(a => a.carColorId == carColorId)
                .Include(a => a.carColor)
                .Include(a => a.Filter);
        return View("_Index", carColorsfilters.ToList());
    }

此视图显示为模式弹出窗口。

当模式第一次加载时,我仔细检查了 ID 的 HTML 隐藏字段(使用查看源代码),它们都是正确的。但是,当我单击删除按钮时,无论哪一行,第一行的 ID 总是传递给操作。

然后,如果我立即再次检查 HTML 隐藏字段,ID 的所有隐藏字段都是完全相同的,即 ORIGINAL 第一行的 ID(在原始删除单击中被删除),所以出现错误发生。

任何想法为什么会发生这种情况?

这是模态动作的源代码...

    <script type="text/javascript">


    $(function () {
        $.ajaxSetup({ cache: false });

        $("a[data-modal]").on("click", function (e) {
            // hide dropdown if any (this is used wehen invoking modal from link in bootstrap dropdown )
            //$(e.target).closest('.btn-group').children('.dropdown-toggle').dropdown('toggle');

            $('#myModalContent').load(this.href, function () {
                $('#myModal').modal({
                    /*backdrop: 'static',*/
                    keyboard: true
                }, 'show');
                bindForm(this);
            });
            return false;
        });
    });

    function bindForm(dialog) {
        $('form', dialog).submit(function () {
            $.ajax({
                url: this.action,
                type: this.method,
                data: $(this).serialize(),
                success: function (result) {
                    if (result.success) {
                        $('#myModal').modal('hide');
                        $('#replacetarget').load(result.url); //  Load data from the server and place the returned HTML into the matched element
                    } else {
                        $('#myModalContent').html(result);
                        bindForm(dialog);
                    }
                }
            });
            return false;
        });
    }
</script>

【问题讨论】:

  • 你能详细说明“第二次”是什么意思吗?
  • @Shyju 这张桌子很完美。 3 行,全部带有单独的 id 和删除按钮等。我单击删除,它运行良好,行消失。我在另一行上单击删除,但它失败了。原因是传递给控制器​​的 item.id 是原始的(已删除。)
  • 你有一些拦截删除表单提交的js代码吗?
  • @Shyju 不,我没有
  • 而就返回视图时的id 值而言,这是因为id 已在POST 方法中添加到ModelState。您可以在 return View(..) 语句之前使用 ModelState.Clear() 来解决这个问题。

标签: c# asp.net-mvc razor


【解决方案1】:

您的问题可能与这两行有关:

@Html.Hidden("id", item.Id)
@Html.Hidden("carColorId", (Int32)ViewBag.carColorId)

它们处于循环中,并且隐藏字段的名称被设置为静态值(id 和 carColorId)。这会在每次迭代中产生具有相同名称的隐藏字段,从而导致您的问题是“第一个”id 总是被传递给操作。作为旁注,这是无效的,因为元素 ID 对于整个文档来说是唯一的。无论如何,我建议您更改以下内容:

@* Switch to a for loop to allow using the iterator variable to create
   unique names and ids for the fields *@
@for (var i = 0; i < Model.Count; i++)

@Html.HiddenFor(m => m[i].Id)
@Html.HiddenFor(m => m[i].CarColorId) 

我假设您的模型实际上是 IEnumerable 或类似的,并且 CarColorId 是模型上第二个隐藏字段的属性名称 - 您需要在控制器中填充它,而不是使用 ViewBag。

希望对您有所帮助。

【讨论】:

  • 对于具有相同名称的字段,您可能是正确的,但您提出的答案不适用于与 @Html.HiddenFor(m =&gt; m[i].Id) 一样的绑定,您最终会得到 name="[1].Id"name="[2].Id" 等。
  • 好点@JudgeBread!我通常在模型的单独属性中拥有这样的集合,而不是作为模型本身,所以我会有类似m =&gt; m.myCollection[i].Id
  • 重复的name 属性是完全有效的(尽管重复的id 属性不是)。但是 OP 在每次迭代中都会创建一个表单,所以它需要生成 name="id" 所以这不起作用
【解决方案2】:

Sleeyuen 认为重复的名称是导致问题的原因,因此我个人会对您采取不同的方法。

在页面上可能在您的表格之后有一个命名的隐藏表单。

@using (Html.BeginForm("DeleteFromModal", "carColorsFilters", FormMethod.Post, new { name = "deleteFrm", id = "deleteFrm" }))
{
    @Html.Hidden("id", item.Id)
    @Html.Hidden("carColorId", (Int32)ViewBag.carColorId)
}

您的删除按钮应该只有 button 类型,并且具有要删除的 ID 作为 data- 属性。

<input class="btn btn-primary deleteCarColorBtn" type="button" value="Delete" data-delete-id="item.id" data-car-color-id="(Int32)ViewBag.carColorId" />

然后在按钮的单击事件上,您可以读取 deleteid,将其传递给您的表单并提交。

var deleteId = $(".deleteCarColorBtn").data('deleteId');
var carColorId = $(".deleteCarColorBtn").data('carColorId');
$("#id").val(deleteId);
$("#carColorId").val(carColorId);
$("#deleteFrm").submit();

【讨论】:

    【解决方案3】:

    感谢@StephenMuecke 的正确回答。

    一旦我执行了 ModelState.Clear(),它似乎工作得更好!

    如果你能告诉我如何用答案奖励你,请告诉我。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-24
      • 2011-06-03
      相关资源
      最近更新 更多