簡體   English   中英

無法將可枚舉的 model 傳遞給 controller?

[英]Can't pass an enumerable model to a controller?

我有點困惑,因為我認為這是一件非常直截了當的事情,這可能是一些簡單的事情讓我絆倒了。

我有一個看法:

@model IEnumerable<CarViewModel>

@using (Html.BeginForm("SummarySaveAll", "VroomVroom", FormMethod.Post))
{
  @Html.AntiForgeryToken()
  <div>
    <table>
        <thead>
            <tr>
                <th width="1">
                    @Html.DisplayNameFor(model => model.Driver)
                </th>
                <th width="1">
                    @Html.DisplayNameFor(model => model.Colour.Name)
                </th>
            </tr>
        </thead>

        <tbody>
            @foreach (var element in Model)
            {
                <tr>
                    <td width="1">
                        @Html.DisplayFor(m => element.Driver)
                    </td>
                    <td width="1">
                        @Html.DropDownListFor(m => element.Colour, element.Colours, "Unknown")
                    </td>
                </tr>
            }
        </tbody>
    </table>
    <div>
        <input type="submit" value="Save Changes" class="btn" />
        @Html.ActionLink("Cancel Changes", "Index", null, new { @class = "btn" })
    </div>
  </div>
}

並且CarViewModel的列表/可枚舉應該反彈回VroomVroom controller,它執行的操作SummarySaveAll - 但頁面上的視圖模型不會傳回給它:

    [HttpPost]
    public ActionResult SummarySaveAll(IEnumerable<CarViewModel> summaries)
    {
        // Want to do stuff with summaries but it's always null
        return View();
    }

我試圖將 List 封裝在另一個 ViewModel 中,並使用for i循環遍歷元素,但這也不會傳回 controller。

當然可以將模型的列表或 IEnumerable 發送回 controller?

我的汽車虛擬機:

public class CarViewModel
{
    [MaxLength(150)]
    [Display(AutoGenerateField = true, Name = "Entered By")]
    public string Driver { get; set; }

    [Display(AutoGenerateField = true)]
    public Colour Colour { get; set; }

    [Key]
    [Display(AutoGenerateField = false)]
    public int Id { get; set; }

    [Display(AutoGenerateField = false)]
    public bool IsDeleted { get; set; } = false;

    public IEnumerable<SelectListItem> Colours { get; set; }

    public CarViewModel() { }

    public CarViewModel(Model CarModel summaryModel, CarPropertyCollection propertyCollection)
    {
        Driver = summaryModel.Driver;
        Id = summaryModel.Id;
        IsDeleted = summaryModel.IsDeleted;

        Colour = summaryModel.Colour == null ? null :
            propertyCollection.Colours.Where(x => x.Id == summaryModel.Colour.Id).FirstOrDefault();

        Colours = propertyCollection.Colours.Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.Name });

    }
}

}

必須強調Colour是自定義的 class 但只有 Id 和 Name 屬性

嘗試

[HttpPost]
public ActionResult SummarySaveAll(IList<CarViewModel> summaries)
{
    // Want to do stuff with summaries but it's always null
    return View(summaries);
}

我還添加了這個 model 作為參數供您查看

Colours與特定汽車無關,它與一般汽車有關,因此與其使用集合作為視圖 model,不如創建一個包裝器:

class EditCarsViewModel
{
    public IEnumerable<SelectListItem> Colours { get; set; }

    public IList<CarViewModel> Cars { get; set; }
}

那么你的看法:

@model EditCarsViewModel

@for (int i = 0; i < Model.Cars.Length; i++)
{
    <td>
        @Html.DropDownListFor(m => Model.Cars[i].Colour, Model.Colours, "Unknown")
    </td>
}

任何其他CarViewModel屬性也需要自己的輸入。 如果它們應該是只讀的,則可以使用HiddenFor

@model EditCarsViewModel

@for (int i = 0; i < Model.Cars.Length; i++)
{
    @Html.HiddenFor(m => Model.Cars[i].Id)
    @Html.HiddenFor(m => Model.Cars[i].Driver)
    <!-- etc. -->
    <td>
        @Html.DropDownListFor(m => Model.Cars[i].Colour.Id, Model.Colours, "Unknown")
    </td>
}

還有你的 controller:

[HttpPost]
public ActionResult SummarySaveAll(EditCarViewModel model)
{
    // model.Cars should be populated
    return View();
}

請注意,應使用IList<T>等可索引集合,因為表單字段名稱需要包含索引以區分項目。

由 OP 編輯Colour class 由一個[Key] int Id屬性和一個string Name屬性組成。 對於DropDownList項目,我必須確保在m => Model.Cars[i].Colour.Id行上指定了Id屬性,否則該特定道具將作為 null 返回,即使其他項目運行良好。

這是你如何做的:

首先是我的視圖,它回發到一個名為 Home 的 controller 和一個名為 ListView 的操作:

@model List<MyModel>
@{
    ViewData["Title"] = "Using a list as model";
}
<h1>@ViewData["Title"]</h1>

@using (Html.BeginForm("ListView", "Home", FormMethod.Post))
{
  @Html.AntiForgeryToken()
  <div>
    <table>
        <thead>
            <tr>
                <th width="1">
                    Name
                </th>
                <th width="1">
                    Description
                </th>
            </tr>
        </thead>

        <tbody>
            @for (var i = 0; i < Model.Count; i++)
            {
                <tr>
                    <td width="1">
                        @Html.DisplayFor(m => Model[i].Name)
                    </td>
                    <td width="1">
                        @Html.TextBoxFor(m => Model[i].Description)
                    </td>
                </tr>
            }
        </tbody>
    </table>
    <div>
        <input type="submit" value="Save Changes" class="btn" />
        @Html.ActionLink("Cancel Changes", "Index", null, new { @class = "btn" })
    </div>
  </div>
}

請注意我如何使用索引器來呈現控件[i]

這是我的 model:

  public class MyModel
  {
    public string Name { get; set; }
    public string Description { get; set; }
  }

這是我的 controller 操作:

[HttpPost]
public IActionResult ListView(IEnumerable<MyModel> model)
{

  return View(model);
}

這是結果:

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM