【问题标题】:How to bind a list of objects in ASP.NET Core MVC when the posted list is smaller than original?当发布的列表小于原始列表时,如何在 ASP.NET Core MVC 中绑定对象列表?
【发布时间】:2019-03-29 10:34:38
【问题描述】:

在表单上的输入上使用“禁用”属性不会发布它们,这是预期和想要的。但是,如果您在列表中准备 3 个对象的表单,禁用第一个和第三个,然后提交,则第二个对象出现在 post header 中,但没有正确绑定到列表,因为它有一个索引 [1] 而不是[0]。

我了解模型绑定的工作原理以及它为什么不绑定我想要的已发布对象,但我不知道如何描述该问题以获得能够引导我找到解决方案的具体结果。我搜索的任何内容都会指向基本的帖子和绑定示例。

在我正在使用的模型中列出:

public IList<_Result> Results { get; set; }

类 _Result 具有以下属性之一:

public string Value { get; set; }

我填写列表并在视图中使用它,如下所示:

@for (int i = 0; i < Model.Results.Count; i++)
{
    ...
    <td>
        <input asp-for="Results[i].Value" disabled />
    </td>
    ...
}

我在表单上有复选框,它(使用 javascript)从输入中删除“禁用”属性,从而允许发布它们。

当我用 3 个 _Result 对象填充上述列表时,它们会显示在表单上并且都具有“禁用”属性。如果我从前两个对象中删除“禁用”属性并单击提交按钮,我会收到包含前 2 个 _Result 对象的结果列表,这是预期的。

但是,如果我仅从第二个 _Result 对象中删除“禁用”属性(第一个 _Result 对象仍然具有“禁用”属性),则结果列表在我的 Controller 方法中返回为空。 在我的表单数据页眉中,我看到:“Results[1].Value: Value that I want posted”,这意味着 post 发生了,但由于索引,list 没有绑定对象。

知道如何实现正确的绑定吗?另外,我使用“禁用”属性的原因是因为我在一个页面上显示了许多结果,并且只想发布那些被选中的结果。

【问题讨论】:

    标签: view asp.net-core-mvc model-binding


    【解决方案1】:

    为了获取选定的项目,您可以尝试使用 View Model 的复选框,而不是使用 jquery 来控制禁用属性。

    1. 更改视图模型

      public class ModelBindVM
      {
          public IList<_ResultVM> Results { get; set; }
      }
      public class _ResultVM
      {
          public bool IsSelected { get; set; }
          public string Value { get; set; }
      }
      
    2. 控制器

      [HttpGet]
      public IActionResult ModelBindTest()
      {
          ModelBindVM model = new ModelBindVM
          {
              Results = new List<_ResultVM>() {
                  new _ResultVM{ Value = "T1" },
                  new _ResultVM{ Value = "T2" },
                  new _ResultVM{ Value = "T3" }
              }
          };
          return View(model);
      }
      [HttpPost]
      public IActionResult ModelBindTest(ModelBindVM modelBind)
      {
          return View();
      }
      
    3. 查看

      <div class="row">
          <div class="col-md-4">
              <form asp-action="ModelBindTest">
                  @for (int i = 0; i < Model.Results.Count; i++)
                  {
                      <input type="checkbox" asp-for="Results[i].IsSelected" />
                      <label asp-for="@Model.Results[i].IsSelected">@Model.Results[i].Value</label>
                      <input type="hidden" asp-for="@Model.Results[i].Value" />
                  }
                  <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                  <div class="form-group">
                      <input type="submit" value="Save" class="btn btn-primary" />
                  </div>
              </form>
          </div>
      </div>
      

    【讨论】:

    • 这样做,它也会发布“IsSelected”属性。如果我显示 1000 个结果,这将使其成为 2000 个项目的帖子。我想要实现的是,如果我显示 1000 个结果并且只选择了 5 个,我只想发布这 5 个(并正确绑定它们)。
    • @Dely 你可以通过IsSelected 是否为真来过滤modelBind
    • 我该怎么做?你能指出我正确的方向吗?
    • @Dely try var selected = modelBind.Results.Where(r =&gt; r.IsSelected).ToList();
    • 好的,但那是过滤已经绑定的结果。如果我在浏览器的开发工具中签入 Headers->Form Data,我仍然会发布所有结果(很多)。我的目标是只发布那些被选中的结果,而不是在发布后过滤它们。
    猜你喜欢
    • 2020-03-14
    • 2019-08-06
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    相关资源
    最近更新 更多