Я пытаюсь реализовать Редактирование ViewModel для моего объекта Linq2SQL, названного продуктом. Этому связали внешний ключ со списком брендов.
В настоящее время я заполняю список бренда через ViewData и использую DropDownListFor, таким образом:
<%= Html.DropDownListFor(model => model.BrandId, (SelectList)ViewData["Brands"])%>
<%= Html.ValidationMessageFor(model => model.BrandId) %>
Теперь я хочу осуществить рефакторинг представление для использования ViewModel со строгим контролем типов и HTML. EditorForModel ():
<% using (Html.BeginForm()) {%>
<%= Html.ValidationSummary(true) %>
<% } %>
В моем Редактировании ViewModel у меня есть следующее:
public class EditProductViewModel
{
[HiddenInput]
public int ProductId { get; set; }
[Required()]
[StringLength(200)]
public string Name { get; set; }
[Required()]
[DataType(DataType.Html)]
public string Description { get; set; }
public IEnumerable Brands { get; set; }
public int BrandId { get; set; }
public EditProductViewModel(Product product, IEnumerable brands)
{
this.ProductId = product.ProductId;
this.Name = product.Name;
this.Description = product.Description;
this.Brands = brands;
this.BrandId = product.BrandId;
}
}
Контроллер является установкой как так:
public ActionResult Edit(int id)
{
BrandRepository br = new BrandRepository();
Product p = _ProductRepository.Get(id);
IEnumerable brands = br.GetAll().ToList().ToSelectListItems(p.BrandId);
EditProductViewModel model = new EditProductViewModel(p, brands);
return View("Edit", model);
}
ProductId, Имя и Описание отображаются правильно в сгенерированном представлении, но список выборки не делает. Список бренда определенно содержит данные.
Если я делаю следующее, по моему мнению, SelectList видим:
<% using (Html.BeginForm()) {%>
<%= Html.ValidationSummary(true) %>
<% } %>
Что я делаю неправильно? EditorForModel () не в общем поддерживают SelectList? Я пропускаю некоторый DataAnnotation?
Я, может казаться, не нахожу примеры использования SelectList в ViewModels той справкой. Я действительно озадачен. Этот ответ, кажется, близок, но не помог.
Junto,
метод Html.EditorForModel()
недостаточно умен, чтобы сопоставить BrandId
со списком Brands
.
Во-первых, вы не можете использовать метод EditorForModel()
.
Вы должны создать свой собственный HTML-шаблон, как здесь.
<% using (Html.BeginForm()) { %>
<div style="display:none"><%= Html.AntiForgeryToken() %></div>
<table>
<tr>
<td><%= Html.LabelFor(m => m.Name) %></td>
<td><%= Html.EditorFor(m => m.Name) %></td>
</tr>
<tr>
<td><%= Html.LabelFor(m => m.Description) %></td>
<td><%= Html.EditorFor(m => m.Description) %></td>
</tr>
<tr>
<td><%= Html.LabelFor(m => m.BrandId) %></td>
<td><%= Html.EditorFor(m => m.BrandId) %></td>
</tr>
</table>
<% } %>
Во-вторых, вам нужно изменить метод Action.
[ImportModelStateFromTempData]
public ActionResult Edit(int id)
{
BrandRepository br = new BrandRepository();
Product p = _ProductRepository.Get(id);
ViewData["BrandId"] = br.GetAll().ToList().ToSelectListItems(p.BrandId);
EditProductViewModel model = new EditProductViewModel(p);
return View("Edit", model);
}
В-третьих, вам нужно обновить класс EditProductViewModel
.
public class EditProductViewModel
{
[Required]
[StringLength(200)]
public string Name { get; set; }
[Required()]
[DataType(DataType.Html)]
public string Description { get; set; }
[Required] // this foreign key *should* be required
public int BrandId { get; set; }
public EditProductViewModel(Product product)
{
this.Name = product.Name;
this.Description = product.Description;
this.BrandId = product.BrandId;
}
}
Сейчас вы, вероятно, говорите: Чувак, где мое свойство [ProductId]?".
Короткий ответ: Оно вам не нужно!
HTML, отображаемый вашим представлением, уже указывает на метод действия "Edit" с соответствующим "ProductId", как показано ниже.
<form action="/Product/Edit/123" method="post">
...
</form>
Это ваш метод действия HTTP POST и он принимает 2 параметра.
"id" берется из атрибута действия тега
Вы должны встроить этот поиск в свою модель просмотра. Затем создайте объект Builder, который строит ViewModel и заполняет этот поиск.
В конце концов, именно для этого и предназначена ваша ViewModel: чтобы предоставить модель специально для вашего представления.
Новый атрибут DropDownList для вашего свойства BrandId может быть полезен. Просмотрите статью Расширение шаблонов ASP.NET MVC 2. Но этот подход использует ViewData в качестве источника элементов списка selectlist.