使用数组属性绑定模型以在 ASP.NET Core MVC 中形成 [英] Bind model with array property to form in ASP.NET Core MVC

查看:26
本文介绍了使用数组属性绑定模型以在 ASP.NET Core MVC 中形成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想弄清楚如何将表单元素绑定到包含数组或可枚举属性的模型.此表单应可用于添加新对象或编辑现有对象.

下面是一个精简的例子.

如果 Levels 不包含任何元素(例如 create),则不会呈现 Level 字段行.您应该向 Level 数组添加一个空元素还是应该添加一行空字段?但是如何使用 asp-for 属性做到这一点.

如果 Levels 包含元素(例如编辑),则渲染 Level 字段的行.但是,在 Edit 方法中发布 model.Levels 时为 null.

任何想法如何最好地实现这一点?

绑定模型

公共类 CarparkModel{[隐藏输入]公共 int Id { 获取;放;}公共字符串名称 { 获取;放;}公共级别[] 级别{ 获取;放;}}公开课级别{[隐藏输入]公共 int Id { 获取;放;}公共字符串 描述 { 获取;放;}公共 int NrOfSpaces { 得到;放;}}

主视图

@model CarparkModel<表单方法=POST"><输入 asp-for="Id"><div><label asp-for="Name"></label><输入 asp-for="名称">

<表格><tr><第>描述第<第Nr个空格</tr>@foreach(Model.Levels 中的级别级别){<tr><td><input asp-for="Description"></td><td><input asp-for="NrOfSpaces"></td></tr>}<tr><td colspan="2><!-- 单击 = 添加了新的级别字段行 --><button type="button">添加级别</button></td></tr><button type="submit">保存</button></表单>

控制器

公共类 CarparkController{[HttpGet]公共 IActionResult 创建(){返回视图(新停车场模型());}[HttpPost]公共 IActionResult 创建(停车场模型模型){如果(模型状态.IsValid){_repository.Save(模型);return RedirectToAction("index");}返回视图(模型);}[HttpGet]公共 IActionResult 编辑(int id){返回视图(_repository.Get(id));}[HttpPost]公共 IActionResult 编辑(停车场模型模型){如果(模型状态.IsValid){_repository.Save(模型);return RedirectToAction("index");}返回视图(模型);}}

解决方案

不要使用 foreach 如果您希望能够在表单中发回项目.使用带有索引命名的 for 循环.

@model CarparkModel<表单方法=POST"><输入 asp-for=Id"><div><label asp-for="Name"></label><input asp-for=名称">

<表格><tr><第>描述第<第Nr个空格</tr>@for(var index = 0, index < Model.Levels.Length, index++){<tr><td><input asp-for=@Model.Levels[index].Description"></td><td><input asp-for="@Model.Levels[index].NrOfSpaces"</td></tr>}<tr><td colspan=2"><!-- 单击 = 添加了新的级别字段行 --><button type="button">添加级别</button></td></tr><button type="submit">Save</button></表单>

在表单中发布集合时需要索引来重建集合.

I'm trying to figure out how to bind form elements to model containing a property that is an array or enumerable. This form should be usable for adding a new object or editing an existing one.

Below is a stripped down example.

If Levels contains no elements (e.g. create), the row of Level fields is not rendered. Should you add an empty element to the Level array or should you add a row of empty fields? But how to do this using the asp-for attribute.

If Levels contains elements (e.g. edit), the rows of Level fields is rendered. However, when posting model.Levels in the Edit method is null.

Any ideas how to best implement this?

Model to bind

public class CarparkModel
{
  [HiddenInput]
  public int Id { get; set; }
  public string Name { get; set; }
  public Level[] Levels { get; set; }
}

public class Level
{
   [HiddenInput]
   public int Id { get; set; }
   public string Description { get; set; }
   public int NrOfSpaces { get; set; }
}

Main view

@model CarparkModel

<form method="POST">
  <input asp-for="Id">
  <div>
    <label asp-for="Name"></label>
    <input asp-for="Name">
  </div>
  <table>
    <tr>
      <th>Description</th>
      <th>Nr of spaces</th>
    </tr>
  @foreach (Level level in Model.Levels)
  {
    <tr>
      <td><input asp-for="Description"></td>
      <td><input asp-for="NrOfSpaces"></td>
    </tr>
  }
    <tr>
      <td colspan="2>
        <!-- Click = new row of Level fields added -->
        <button type="button">Add level</button>
      </td>
    </tr>
  </table>
  <button type="submit">Save</button>
</form>

Controller

public class CarparkController
{
  [HttpGet]
  public IActionResult Create()
  {
    return View(new CarparkModel());
  }

  [HttpPost]
  public IActionResult Create(CarparkModel model)
  {
    if (ModelState.IsValid)
    {
      _repository.Save(model);
      return RedirectToAction("index");
    }

    return View(model);    
  }

  [HttpGet]
  public IActionResult Edit(int id)
  {
    return View(_repository.Get(id));
  }

  [HttpPost]
  public IActionResult Edit(CarparkModel model)
  {
    if (ModelState.IsValid)
    {
      _repository.Save(model);
      return RedirectToAction("index");
    }

    return View(model);    
  }
}

解决方案

Don't use foreach if you want to be able to send the items back in the form. use for loop with indexed naming for the items.

@model CarparkModel

<form method="POST">
  <input asp-for="Id">
  <div>
    <label asp-for="Name"></label>
    <input asp-for="Name">
  </div>
  <table>
    <tr>
      <th>Description</th>
      <th>Nr of spaces</th>
    </tr>
  @for(var index = 0, index < Model.Levels.Length, index++)
  {
    <tr>
      <td><input asp-for="@Model.Levels[index].Description"></td>
      <td><input asp-for="@Model.Levels[index].NrOfSpaces"></td>
    </tr>
  }
    <tr>
      <td colspan="2">
        <!-- Click = new row of Level fields added -->
        <button type="button">Add level</button>
      </td>
    </tr>
  </table>
  <button type="submit">Save</button>
</form>

The index is needed to reconstruct the collection when posting it in the form.

这篇关于使用数组属性绑定模型以在 ASP.NET Core MVC 中形成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
C#/.NET最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆