【问题标题】:MVC Html.HiddenFor in a loop passing model back to ControllerMVC Html.HiddenFor 在循环中将模型传递回控制器
【发布时间】:2018-01-06 10:30:15
【问题描述】:

我正在循环浏览我的模型的 IEnumerable:

@model IEnumerable<Testing.Models.ProductItem>
@{
    ViewBag.Title = "Buy Products";
}

<div class="row">
    @foreach (var product in Model)
    {
        using (Html.BeginForm())
        {
            @Html.HiddenFor(Model => product)
            ... More Controls and stuff...
            <input type="submit" value="Add To Kart" class="btn btn-info">

        }

    }
</div>

在提交时,我想将选定的模型实例传回我的控制器:

    [HttpPost]
    public ActionResult Index(ProductItem product)
    {
        ... Do Stuff ...
        return View();
    }

但是我尝试了一些事情,但似乎总是将 null 传递到控制器中...请有人帮我指出正确的方向吗?

编辑

我实际上不需要完整的模型实例,因为我可以从 ID 在控制器中获取它 - 所以我尝试了以下方法:

@model IEnumerable<Testing.Models.ProductItem>
@{
    ViewBag.Title = "Buy Products";
}

<div class="row">
    @foreach (var product in Model)
    {
        using (Html.BeginForm())
        {
            @Html.HiddenFor(Model => product.ID)
            @Html.TextBox("qty", "1", htmlAttributes: new { @style = "width: 30px;" })

            ... More Controls and stuff...

            <input type="submit" value="Add To Kart" class="btn btn-info">

        }

    }
</div>

向控制器发帖:

[HttpPost]
public ActionResult Index([Bind(Include = "ID")] int? ID, [Bind(Include = "qty")] int? qty)
{
    return null;
}

文本框不是模型的一部分,因为它是用户输入 - 这个值很好地传递给了 actions 参数,但是我仍然在 HiddenFor 控件中得到一个空值。这与控件的命名有关吗?我似乎无法为 HiddenFor 控件添加名称。

我知道这对最初的问题有不同的看法,但我希望你仍然能够提供帮助。

我注意到 BeginForm 在循环内 - 为列表中的每个项目创建...有没有一个简单的替代方法(注意我还没有尝试过任何东西)。

【问题讨论】:

  • 您的代码存在多个问题。首先,您不能将复杂对象绑定到表单控件(如果是模型,则需要绑定每个属性)。并且为集合中的每个项目设置一个表单是没有意义的 - 您一次只能提交一个表单,并且在任何情况下您都会生成与您的模型无关的输入
  • 要么使用for 循环或EditorTemplate 在单个表单中生成表单控件,然后在一个操作中提交所有内容(请参阅this answer),或者如果您只想更新一个项目有一次,使用 ajax 或有一个链接将您重定向到一个页面以编辑该项目
  • 谢谢...鉴于此,我已将问题更新为传递 ID 而不是完整模型。如果您能够看一下并让我知道您现在的想法会很棒。
  • 你需要阅读之前的cmets和我给你的链接。您的视图没有意义,并且您使用 name="product.ID", but your model does not contain a complex property named product` 生成控件(您的方法中的参数也没有)。你应该删除那些无意义的[Bind] 属性

标签: c# asp.net-mvc submit


【解决方案1】:

听起来您正试图在复杂类型上使用 HiddenFor,但这是行不通的。您需要使用 ProductItem 的属性,例如 ProductId 或类似的东西,它很可能是一个 int 或 Guid。

现在您已经清除了与简单字段的复杂绑定,您会注意到您的名称被设置为 product.id,这就是为什么它在您的控制器中始终为 null。您不能使用 Hidden 覆盖 name 属性,因此您需要将代码更改为:

@foreach (var product in Model)
{
    using (Html.BeginForm())
    {
        @Html.Hidden("ID", product.ID)
        @Html.TextBox("qty", "1", htmlAttributes: new { @style = "width: 30px;" })

        <input type="submit" value = "Add To Kart" class="btn btn-info">
    }

}

【讨论】:

  • 感谢 codepros... 鉴于此,我已将问题稍微更新为传递 ID 而不是完整模型。如果您能够看一下并让我知道您现在的想法会很棒。
  • Heya @CJH,HiddenFor 将自动设置名称和 ID。您可以覆盖 ID,但不能轻易覆盖名称。因此,要获得您想要的功能,您需要使用 Html.Hidden,例如: using (Html.BeginForm()) { Html.Hidden("ID", product.ID) Html.TextBox("qty" , "1", htmlAttributes: new { style = "width: 30px;" }) }
【解决方案2】:

代替Model => product.Id,试试p=> product.Id

   @model IEnumerable<Testing.Models.ProductItem>
   @{
       ViewBag.Title = "Buy Products";
    }

    <div class="row">
    using (Html.BeginForm())
    {
       @foreach (var product in Model)
       {
             @Html.HiddenFor(p => product.ID)
             @Html.TextBox("qty", "1", htmlAttributes: new { @style = "width: 
           30px;" })

            ... More Controls and stuff...         

        }
        <input type="submit" value="Add To Kart" class="btn btn-info">
    }
    </div>

【讨论】:

  • 这仍然会以 product.ID 的名称呈现隐藏的输入,这意味着他的控制器永远不会获取该值(基于它目前的编写方式)。
【解决方案3】:

我已经通过以下方式实现了我想要的功能(正确或错误):

@model List<ShoppingKartTest.Models.ProductItem>
@{
    ViewBag.Title = "Buy Products";
}



@foreach (var item in Model)
{
    using (Html.BeginForm())
    {

       <input type="hidden" value="@item.ID" name="ID" />
       @Html.TextBox("qty", "1", new { @style = "width: 30px;" })


       <input type="submit" value="Add To Kart" class="btn btn-info">
    }
}

哪个正确地将隐藏ID和文本框的内容提交给控制器动作:

[HttpPost]
public ActionResult Index(int ID, int qty)
{
    //... Do stuff with parameters...
    return View();
}

我很想听听任何关于此的 cmets。我知道上面有人告诉我,我不应该将 BeginForm 放在循环中……但这对我有用。

【讨论】:

  • 这段代码本身并没有什么“错误”。它的渲染与我今天早上给你的代码几乎完全一样。纯粹主义者并不是说您的方法行不通,而是说它很丑陋并且与现代最佳实践背道而驰/不可扩展。您的代码不必要地呈现大量表单打开和关闭标签,使您的页面膨胀。更正确和现代的方法是使用单个 Html.BeginForm 或 Ajax.BeginForm 并让您的控制器通过 AJAX 接受“添加到购物车”点击。
  • 感谢 codepros 的反馈...我很感激。我当前的项目永远不会看到生产环境,并且纯粹用作功能示例,所以我可能会逃脱它......这次......
  • 这段代码有很多不好的地方。您没有双向绑定到模型,您没有得到验证,如果您必须返回视图,它将无法正常工作。如果您要编写否定其所有好处的代码,为什么还要使用 MVC。
  • 虽然我同意斯蒂芬所说的大部分内容,但无论出于何种原因,这都不是 OP 想要的。他显然是 MVC 的新手,只想让它发挥作用。很多人都说这不是最好的方法,但显然,他并不关心这一点,但也许比这更重要的是你不知道他的要求。他显然想把它放在门外,并不特别关心质量。我想这就是他和我管理的原因。
  • 感谢你们的 cmets...我对 MVC 很陌生,我发现有时很难从事件驱动的开发中逆势而上(你可能会说)。我确实查看了您的链接斯蒂芬但是时间对我不利,我宁愿'让它工作'然后如果我有时间,重新访问以使其“正确”工作,如果我能够将你的答案转移到我的问题(记住,我是初学者!!!)...如果我这样做了,我肯定会用我的结果更新这篇文章。 Coderpros,我不确定你是在捍卫我的立场还是反对……?不过谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多