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>
<% } %>
Во-вторых, вам нужно изменить метод действия.
[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-код, отображаемый в вашем представлении, уже указывает на метод действия «Изменить» с соответствующим «ProductId», как показано ниже.
<form action="/Product/Edit/123" method="post">
...
</form>
Это ваш метод действия HTTP POST, и он принимает 2 параметра.
«Идентификатор» происходит из атрибута действия тега .
[HttpPost, ValidateAntiForgeryToken, ExportModelStateToTempData]
public ActionResult Edit(int id, EditProductViewModel model)
{
Product p = _ProductRepository.Get(id);
// make sure the product exists
// otherwise **redirect** to [NotFound] view because this is a HTTP POST method
if (p == null)
return RedirectToAction("NotFound", new { id = id });
if (ModelState.IsValid)
{
TryUpdateModel<Product>(p);
_ProductRepository.UpdateProduct( p );
}
return RedirectToAction("Edit", new { id = id });
}
ExportModelStateToTempData
и ImportModelStateFromTempData
очень полезны.
Эти атрибуты используются для шаблона PRG (Post Redirect Get).
Читать это Использовать шаблон PRG для модификации данных раздел в этом сообщении в блоге Кази Манзур Рашид .
http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx
Хорошо, этот код привязки данных не мой любимый способ ведения дел.
TryUpdateModel<Product>( p );
Мой любимый способ сделать это - иметь отдельный interface
для чистого связывания данных.
public interface IProductModel
{
public string Name {get; set;}
public string Description {get; set;}
public int BrandId {get; set;}
}
public partial class Product : IProductModel
{
}
public partial class EditProductViewModel : IProductModel
{
}
И так я обновлю свой код привязки данных.
TryUpdateModel<IProductModel>( p );
Это помогает мне упростить привязку данных к объектам моей модели из данных обратной передачи.
Кроме того, это делает его более безопасным, потому что вы привязываете только те данные, для которых хотите связать. Ни больше, ни меньше.
Дайте мне знать, если у вас возникнут вопросы.