【问题标题】:ASP MVC : Binding dynamically generated submit form to multiple objectsASP MVC:将动态生成的提交表单绑定到多个对象
【发布时间】:2017-08-02 22:34:37
【问题描述】:

我正在做一个课堂实验,其中包括设计一个小型众筹网站。当用户创建一个项目时,系统会询问他想要为他的项目获得多少层奖励。如果此金额大于 0,他将被重定向到奖励/创建页面。 “创建”视图中有一个表单,该表单是根据用户想要的层数生成的。

问题是我不知道如何使用一个提交按钮将“for”循环的每个实例链接到特定的“RewardViewModel”对象,以及如何将所有这些对象传递给控制器。

这是控制器“Get”方法(我知道我可能不得不更改绑定到视图的模型):

public ActionResult Create(int projectid, int amountOfTiers )
    {
        ViewBag.AmountOfTiers = amountOfTiers;
        ViewBag.ProjectTitle = (from p in context.Projects where p.ProjectId == projectid select p).FirstOrDefault().Title;
        RewardViewModel model = new RewardViewModel { ProjectId = projectid };
        return View(model);
    } 

这是视图:

@model CrowdFundMe.ViewModels.RewardViewModel

@{
ViewBag.Title = "Create";
}
<body>
@section Login{
    @Html.Action("_Login", "User")
}
<h2>Create</h2>
<p>You are adding rewards for the project @ViewBag.ProjectTitle</p>
@using (Html.BeginForm("Create", "Reward", FormMethod.Post))
  {
    var u = ViewBag.AmountOfTiers;
    for (int i = 0; i < u; i++)
    {
        var tier = i+1;
        @Html.HiddenFor(model => model.ProjectId)

        @Html.LabelFor(model => model.Tier, "Tier")<br />
        @Html.TextBoxFor(model => model.Tier, new {@Value = tier, @readonly="readonly"})
        <br />
        <br />

        @Html.LabelFor(model => model.Title, "Title")<br />
        @Html.TextBoxFor(model => model.Title)
        @Html.ValidationMessageFor(model => model.Title)
        <br />
        <br />

        @Html.LabelFor(model => model.AmountOfItems, "Quantity available (leave blank if unlimited)")<br />
        @Html.TextBoxFor(model => model.AmountOfItems)
        @Html.ValidationMessageFor(model => model.AmountOfItems)
        <br />
        <br />

        @Html.LabelFor(model => model.Description, "Description")<br />
        @Html.EditorFor(model => model.Description)
        @Html.ValidationMessageFor(model => model.Description)
        <br />
        <br />
    }

    <input type="submit" value="Create" />
  }

【问题讨论】:

    标签: asp.net-mvc


    【解决方案1】:

    您想要创建RewardViewModel 的集合,因此您在视图中的模型必须是一个集合。目前您只传递一个RewardViewModel 实例,然后使用for 循环生成多个具有重复name 属性的表单控件(以及重复的id 属性,这是无效的html)。

    更改 GET 方法以返回集合

    public ActionResult Create(int projectid, int amountOfTiers)
    {
        List<RewardViewModel> model = new List<RewardViewModel>();
        for(int i = 0; i < amountOfTiers; i++)
        {
            model.Add(new RewardViewModel { ProjectId = projectid });
        }
        ViewBag.ProjectTitle = (from p in context.Projects where p.ProjectId == projectid select p).FirstOrDefault().Title;
        return View(model);
    } 
    

    和视图

    @model List<RewardViewModel>
    ....
    @using (Html.BeginForm("Create", "Reward", FormMethod.Post))
    {
        for(int i = 0; i < Model.Count; i++)
        {
            @Html.HiddenFor(m => m[i].ProjectId)
    
            @Html.LabelFor(m => m[i].Title)
            @Html.TextBoxFor(m => m[i].Title)
            @Html.ValidationMessageFor(m => m[i].Title)
            ....
        }
        <input type="submit" value="Create" />
    }
    

    这将使用索引器正确命名您的控件并将发布到

    public ActionResult Create(List<RewardViewModel> model)
    

    旁注:删除new { @Value = tier }(在使用HtmlHelper 方法时不要设置value 属性)并且不清楚为什么要设置Tier 属性readonly - 它的值未在控制器中设置并且不能在视图中更改,因此将其包含在视图中似乎毫无意义。如果您想为属性添加一个连续的数字,请在控制器中执行 - 例如model.Add(new RewardViewModel { ProjectId = projectid, Tier = i + 1 });

    请注意,也不需要使用@Html.LabelFor(model =&gt; model.Tier, "Tier") - 如果显示文本与属性名称匹配,它可以只是@Html.LabelFor(model =&gt; model.Tier)

    【讨论】:

    • 效果很好。感谢您提供所有详细信息。为了回答您关于我的代码的问题,我设置了层值并将其设置为只读,因为用户不应该能够编辑他正在编码的奖励的层级。如果他选择了 2 级奖励,他必须有“第 1 层”和“第 2 层”,并且不能在“第 5 层”和“第 8 层”中进行编辑。
    • 只要确保您没有在视图中设置value 属性。在将模型传递给视图之前将其设置在控制器中,正如我在最后一段中提到的那样
    • 我在控制器的 Create get 方法中创建每个新对象时添加了“Tier = i+1”,而不是在视图中设置值。再次感谢您的宝贵建议。
    猜你喜欢
    • 1970-01-01
    • 2018-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多