Во-первых, вы можете перечислить только enumerable, то есть IEnumerable<T>
, List<T>
и т. Д. Прямо сейчас у вас есть только один элемент в качестве модели, поэтому foreach
очевидно завершится ошибкой.
Предполагая, что вы действительно возвращаете перечислимую модель, ваша следующая проблема - привязка модели. Чтобы правильно привязать данные, которые вы публикуете, к параметру вашего действия, типы списков должны быть названы в соответствии с форматом CollectionProperty[N].Property
, где N
- это индекс. Чтобы такие вещи, как помощники тегов, могли генерировать правильные name
атрибуты во входных данных формы, им необходимо полное выражение модели. Вы можете думать о выражении модели как о карте определенного свойства, к которому вы пытаетесь привязаться.
Допустим, вы спросили меня, как добраться до места. В идеале вам понадобятся шаги, чтобы начать с того места, где вы сейчас находитесь. Если бы я начал свои указания из какого-то другого места, это не сильно помогло бы, потому что тогда вам понадобятся направления к этому месту сначала, прежде чем вы сможете следовать моим указаниям к конечному пункту назначения.
Здесь концепция аналогична. Использование foreach
и создание переменной item
в основном удаляет первую часть направлений. Помощники тегов знают, как перейти от item
к свойству, к которому вы привязаны, но они не знают, как добраться до item
. Таким образом, вы получите такие имена, как item.Foo
, которые не смогут быть привязаны к чему-либо значимому. Вместо этого вам нужно использовать цикл for
и полное выражение модели, используя индекс в цикле:
@for (var i = 0; i < Model.Count; i++) // assuming `Model` is a list
{
<input asp-for="@Model[i].Foo" />
}
Стоит отметить, что значение asp-for
выше - это специальная конструкция, необходимая, потому что Model
сам по себе является списком, который вы повторяете. Если бы вместо этого это было свойство списка в модели, вы бы просто использовали asp-for="ListProperty[i].Foo"
. Часть @Model
существует просто потому, что перед индексирующей нотацией должен использоваться какой-то фактический член. Я видел, как люди запутались в этом и начали пытаться поставить @Model
перед всем, то есть @Model.ListProperty[i].Foo
.
ИЗМЕНИТЬ
OK. Думаю, я знаю, куда вы сейчас собираетесь, но ваш вопрос был неверным, чтобы передать это. Если вы ищете способ автоматически генерировать входные данные для каждого члена модели, не переходя каждый член за другим, то ответ, в общем, неясен.
Есть Html.EditorFor
и Html.EditorForModel
(которые, как я думаю, все еще существуют в ASP.NET Core ... Я не использую их лично). Оба являются «шаблонными помощниками», что означает, что они полагаются на шаблоны, чтобы определить, как они обрабатывают то, что им передается. Поскольку вы работаете со своей моделью непосредственно здесь, вам понадобится Html.EditorForModel
, который вы использовали бы буквально с помощью следующего кода вместо всего остального кода текущего представления:
@Html.EditorForModel()
Из этого ящика он будет смотреть на каждого члена и генерировать набор входных данных и меток для каждого в соответствии с конкретными типами членов, которые в конечном итоге будут выглядеть примерно так:
<label for="Id">Id</label>
<input id="Id" name="Id" value="" />
<label for="Aktie">Aktie</label>
<input id="Aktie" name="Aktie" value="" />
<label for="Depotname">Depotname</label>
<input id="Depotname" name="Depotname" value="" />
...
С этим есть несколько очевидных проблем. В нем нет ваших классов или структуры Bootstrap, поэтому он будет выглядеть ужасно. Это очень просто в интерпретации типа для отображения ввода. Например, Id
- это то, чего на самом деле, вероятно, вообще не должно быть, или, если он присутствует, это должен быть скрытый ввод. Aktie
может быть длинным текстовым полем, но вы всегда получите ввод, а не что-то вроде textarea
. Возможно, Depotname
должен быть select
со списком возможных вариантов, но, опять же, вы получите только базовый ввод текста. Этот список можно продолжить.
Некоторые из них можно исправить легче, чем другие. Чтобы получить скрытый ввод, примените атрибут [HiddenInput]
к свойству в вашем классе. Атрибут DataType
может быть применен, чтобы дать больше контекста. Например, если вам нужен textarea
, вы можете применить [DataType(DataType.MultilineText)]
к свойству в вашем классе. Если вам нужно изменить текст метки, вы можете сделать это с помощью [Display(Name = "My Label Text")]
.
Для более сложных вещей здесь начинают появляться шаблоны. Например, вы можете создать представление типа Views\Shared\EditorTemplates\String.cshtml
и внутри добавить:
@model string
<div class="form-group row">
<label asp-for="@Model" class="col-lg-3 control-label text-lg-right pt-2" for="inputRounded"></label>
<div class="col-lg-6">
<input asp-for="@Model" class="form-control input-rounded" id="inputRounded" />
</div>
<span asp-validation-for="@Model" class="text-danger"></span>
Then, this will be used for any string
type member. As you might imagine, you can add other such views like DateTime.cshtml
, Int32.cshtml
, etc., which will each be used for their respective types. You can also add templates for any of the members of that DataType
enum, so you can have MultilineText.cshtml
, EmailAddress.cshtml
, etc. Finally, there is a UIHint
attribute that can be applied to specify any template. For example, if you applied [UIHint("Foo")]
to a property, then Foo.cshtml
would be used.
Вы также можете создавать шаблоны для своих собственных типов. Так, например, у вас может быть ProtokollDividenden.cshtml
, и тогда это представление будет фактически использоваться в качестве шаблона для этого класса, а это значит, что оно будет использоваться для вашего вызова @Html.EditorForModel()
.
Однако при всем этом важно отметить, что после того, как вы добавите настраиваемый шаблон, теперь вы несете за это 100% ответственность. Другими словами, если бы вы добавили представление для всей своей модели, тогда это возьмёт верх, и Html.EditorForModel
фактически больше не будет генерировать отдельные поля для вас, в основном вернув вас к той же проблеме, с которой вы начали. Вместо этого он просто сбросит ваш настраиваемый шаблон и прекратит работу.
person
Chris Pratt
schedule
08.03.2019
foreach
. Вы не можете перечислить одиночное значение. Вы перечисляете списки, массивы, словари и т. Д.foreach (var item in Model)
должен вызывать исключение. Если вы знаете, что у вас есть одно значение, нет причин использоватьforeach
- person Panagiotis Kanavos   schedule 08.03.2019