Не можете передать перечисляемую модель контроллеру? - PullRequest
0 голосов
/ 24 апреля 2020

Я немного сбит с толку, потому что я думал, что это очень прямолинейная вещь, возможно, это что-то простое сбивает меня с толку.

У меня есть вид:

@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>
}

и list / enumerable из CarViewModel должен возвращаться к контроллеру VroomVroom, действие SummarySaveAll, которое он выполняет, но модель просмотра на странице не передается обратно:

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

Я пытался инкапсулировать Список в другой ViewModel и циклически проходить по элементам, используя for i l oop, но это также не вернулось бы к контроллеру.

Конечно, можно отправить Список или IEnumerable моделей обратно в контроллер?

My CarVM:

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 является пользовательским классом, но только имеет свойства Id и Name

Ответы [ 3 ]

1 голос
/ 24 апреля 2020

Colours не относится к конкретному автомобилю c, оно относится к автомобилям в целом, поэтому вместо использования коллекции в качестве модели вида создайте обертку:

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>
}

И ваш контроллер:

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

Обратите внимание, что должна использоваться индексируемая коллекция, такая как IList<T>, так как имена полей формы должны включать индекс, чтобы различать элементы.

Редактировать с помощью OP Класс Colour состоит из свойства [Key] int Id и свойства string Name. Для DropDownList предметов я должен был убедиться, что свойство Id было указано в строке m => Model.Cars[i].Colour.Id, в противном случае этот конкретный реквизит возвращался как нулевой, даже если другие предметы проходили нормально.

1 голос
/ 24 апреля 2020

Вот как вы это делаете:

Сначала My View, который отправляет обратно на контроллер с именем Home и действием с именем 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>
}

Обратите внимание, как я использовал индексатор для рендеринга control [i]

Это моя модель:

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

Это действие моего контроллера:

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

  return View(model);
}

И это результат :

enter image description here

1 голос
/ 24 апреля 2020

try

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

Я также добавил эту модель в качестве параметра для вашего просмотра

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...