【问题标题】:ASP.net MVC5 - For loop posts single item but not the collectionASP.net MVC5 - For 循环发布单个项目但不是集合
【发布时间】:2014-07-07 17:00:12
【问题描述】:

我正在创建一个新的食谱输入表单,我发现了两个有趣的问题:

  1. 成分不会发布到配方集合中,并且
  2. 当我将参数设置为集合时,表单只会发布一个成分并发送 null。

理想情况下,我希望成分集合位于配方项下,但我会满足于让成分集合写入参数。

以下是两个模型(由实体框架生成):

食谱:

    public int recipeId { get; set; }

    [Required]
    [StringLength(255)]
    [DisplayName("Name")]
    public string name { get; set; }

    [DisplayName("Category")]
    public int? mealCategoryId { get; set; }

    [DisplayName("Preperation Time")]
    public int? prepTime { get; set; }

    [DisplayName("Cook Time")]
    public int? cookTime { get; set; }

    [DisplayName("Stand Time")]
    public int? standTime { get; set; }

    [DisplayName("Serving Size")]
    public int? servingSize { get; set; }

    [DisplayName("Status")]
    public int recipeStatusId { get; set; }

    [DisplayName("Description")]
    [UIHint("Multiline")]
    public string description { get; set; }

    public virtual ICollection<Direction> Directions { get; set; }

    public virtual ICollection<Image> Images { get; set; }

    public virtual ICollection<Ingredient> Ingredients { get; set; }

    public virtual MealCategory MealCategory { get; set; }

    public virtual ICollection<Nutrition> Nutritions { get; set; }

    public virtual ICollection<Rating> Ratings { get; set; }

    public virtual RecipeStatus RecipeStatus { get; set; }
}

成分:

public partial class Ingredient
    {
        public int ingredientId { get; set; }

        public int? recipeId { get; set; }

        public int? subCategoryId { get; set; }

        public int measurementId { get; set; }

        public int amount { get; set; }

        public virtual Recipe Recipe { get; set; }

        public virtual SubCategory SubCategory { get; set; }

        public virtual Measurement Measurement { get; set; }

    }

查看代码:

   <div class="form-horizontal">
        <h4>Ingredients</h4>
        <hr />
        <table class="table IngredientList">
            <tr>
                <th>
                    @Html.LabelFor(model => model.Recipe.Ingredients)
                </th>
                <th>
                    @Html.LabelFor(model => model.SelectedMeasurementId)
                </th>
                <th>
                    @Html.Label("Amount")
                </th>
            </tr>

            @for (int i = 0; i < Model.Recipe.Ingredients.Count; i++)
            {
                <tr>
                    <td>
                        @Html.DropDownListFor(m => Model.Recipe.Ingredients.ElementAt(i).ingredientId, Model.SubIngredients, new { @class = "form-control input-block-level" })
                    </td>
                    <td>
                        @Html.DropDownListFor(m => Model.Recipe.Ingredients.ElementAt(i).measurementId, Model.Measurements, new { @class = "form-control input-block-level" })
                    </td>
                    <td>
                        @Html.TextBoxFor(m => Model.Recipe.Ingredients.ElementAt(i).amount, new { @class = "form-control input-block-level" })
                    </td>
                </tr>
            }

        </table>
</div>

控制器:

   [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(Recipe recipe, int SelectedCategoryId, List<Ingredient> Ingredients)

    {
        recipe.mealCategoryId = SelectedCategoryId;
        recipe.recipeStatusId = 1;

        if (ModelState.IsValid)
        {
            dbContext.Entry(recipe).State = EntityState.Added;
            dbContext.SaveChanges();
            return RedirectToAction("Details", new {id = recipe.recipeId});
        }

        return View(recipe);
    }

因此,如果我将参数设置为 List Ingredients,则返回 null。如果我将其设置为成分成分,那么我只会得到四种成分中的第一种。 (我将模型设置为在加载时创建 4 个成分记录。)

我的问题是:如何让它通过成分集合?

编辑:

我已确认请求将所有 4 种成分发送过来。绑定好像有问题。

【问题讨论】:

  • 您有什么理由选择在模型定义中使用ICollection&lt;Ingredients&gt; 而不是List&lt;Ingredients&gt;
  • @C Sharper 由实体框架生成。我不确定改变它是否有任何影响。但是,我已经尝试过这样做,但并没有解决问题。
  • 不要使用 EF 生成的模型作为您的“ViewModels”,因此这是不好的做法。创建您自己的模型类并为它们提供所需的属性。

标签: c# asp.net asp.net-mvc controller


【解决方案1】:

创建自己的 ViewModel 来保存数据,不要使用实体框架预生成的类进行模型绑定。这是概念证明的一个非常基本的示例

public class Recipe
{
  public int RecipeId {get; set;}
  public List<Ingredients> Ingredient {get; set;}
} 

public class Ingredients
{
  public string Name {get; set;}
  public string Amount {get; set;}
}

public ActionResult Index()
{
   Recipe model = new Recipe();
   model.RecipeId = 1;
   model.Ingredient = new List<Ingredients>();//Better if done inside Constructor

   model.Ingredient.Add(new Ingredients{Name = "Salt", 
                                        Amount = "A Pinch"});
   model.Ingredient.Add(new Ingredients{Name = "Hot Sauce", 
                                        Amount = "HOT HOT HOT!"});   
  return View(model);
}

查看

@Html.TextBoxFor(x => x.RecipeId)

  for (int i = 0; i < Model.Ingredient.Count; i++)
    {
          @Html.TextBoxFor(modelItem => Model.Ingredient[i].Name)
          @Html.TextBoxFor(modelItem => Model.Ingredient[i].Amount)
    }

并发布它,它会绑定

【讨论】:

  • 这是正确答案。 @Yecats:如果它仍然不起作用,还有其他事情发生,但至少要进行此更改,否则我们将无法为您提供进一步的帮助。
  • 这个答案让我克服了一个我花了 8 个小时试图解决的问题。我将视图模型视为将现有对象放入以传递给视图的袋子,而不是一种以更易于视图使用的方式重新打包现有数据的方法。特别是,为了使视图能够以模型绑定器可以理解的方式回发集合,需要 for 循环和数组表示法。这不能使用存储在我的模型中的 ICollection 对象来完成,但我可以将它转换为我的视图模型中的兼容 List 对象。
猜你喜欢
  • 2012-12-19
  • 2019-08-14
  • 1970-01-01
  • 1970-01-01
  • 2017-08-16
  • 2017-10-27
  • 1970-01-01
  • 2013-11-05
  • 1970-01-01
相关资源
最近更新 更多