我正在尝试为名为Product的Linq2SQL实体实现Edit ViewModel.它有一个与品牌列表相关联的外键.
目前我通过ViewData填充品牌列表并使用DropDownListFor,因此:
<div class="editor-field">
<%= Html.DropDownListFor(model => model.BrandId, (SelectList)ViewData["Brands"])%>
<%= Html.ValidationMessageFor(model => model.BrandId) %>
</div>
Run Code Online (Sandbox Code Playgroud)
现在我想重构视图以使用强类型的ViewModel和Html.EditorForModel():
<% using (Html.BeginForm()) {%>
<%= Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<%=Html.EditorForModel() %>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
Run Code Online (Sandbox Code Playgroud)
在我的编辑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<SelectListItem> Brands { get; set; }
public int BrandId { get; set; }
public EditProductViewModel(Product product, IEnumerable<SelectListItem> brands)
{
this.ProductId = product.ProductId;
this.Name = product.Name;
this.Description = product.Description;
this.Brands = brands;
this.BrandId = product.BrandId;
}
}
Run Code Online (Sandbox Code Playgroud)
控制器设置如下:
public ActionResult Edit(int id)
{
BrandRepository br = new BrandRepository();
Product p = _ProductRepository.Get(id);
IEnumerable<SelectListItem> brands = br.GetAll().ToList().ToSelectListItems(p.BrandId);
EditProductViewModel model = new EditProductViewModel(p, brands);
return View("Edit", model);
}
Run Code Online (Sandbox Code Playgroud)
ProductId,Name和Description在生成的视图中正确显示,但选择列表不会.品牌列表肯定包含数据.
如果我在视图中执行以下操作,则可以看到SelectList:
<% using (Html.BeginForm()) {%>
<%= Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<%=Html.EditorForModel() %>
<div class="editor-label">
<%= Html.LabelFor(model => model.BrandId) %>
</div>
<div class="editor-field">
<%= Html.DropDownListFor(model => model.BrandId, Model.Brands)%>
<%= Html.ValidationMessageFor(model => model.BrandId) %>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?EditorForModel()一般不支持SelectList吗?我错过了某种DataAnnotation吗?
我似乎无法在ViewModels中找到任何有用的SelectList用法示例.我真的很难过.这个答案似乎很接近,但没有帮助.
帮派,
该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>
<% } %>
Run Code Online (Sandbox Code Playgroud)
其次,您需要更改您的 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);
}
Run Code Online (Sandbox Code Playgroud)
第三,你需要更新你的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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可能会说:老兄,我的[ProductId]属性在哪里?”。
简短回答:您不需要它!
您的视图呈现的 HTML 已指向具有适当“ProductId”的“编辑”操作方法,如下所示。
<form action="/Product/Edit/123" method="post">
...
</form>
Run Code Online (Sandbox Code Playgroud)
这是您的 HTTP POST 操作方法,它接受 2 个参数。
“id”来自 <form> 标记的 action 属性。
[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 });
}
Run Code Online (Sandbox Code Playgroud)
和非常有用ExportModelStateToTempData
。
这些属性用于 PRG(重定向后获取)模式。ImportModelStateFromTempData
请阅读Kazi Manzur Rashid撰写的博客文章中的“使用 PRG 模式进行数据修改”部分。http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx
好吧,这个数据绑定代码不是我最喜欢的做事方式。
TryUpdateModel<Product>( p );
Run Code Online (Sandbox Code Playgroud)
我最喜欢的方法是有一个单独的 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
{
}
Run Code Online (Sandbox Code Playgroud)
这就是我更新数据绑定代码的方式。
TryUpdateModel<IProductModel>( p );
Run Code Online (Sandbox Code Playgroud)
这有帮助的是,它使我可以轻松地从回发数据中对模型对象进行数据绑定。此外,它还使其更加安全,因为您只绑定想要绑定的数据。不多不少。
如果您有任何疑问,请告诉我。
归档时间: |
|
查看次数: |
11519 次 |
最近记录: |