MVC 2-当模型类型为 IEnumerable/IQueryable 时更新模型数据
控制器代码:
Function ManagePages() As ActionResult
Dim pages = contentRepository.GetAllContentPagesByType("Content Page", False)
Return View("ManagePages", pages)
End Function
<HttpPost()> _
Function ManagePages(ByVal values As FormCollection) As ActionResult
Dim pages = contentRepository.GetAllContentPagesByType("Content Page", False)
''' **** HOW DO I UPDATE THE MODEL HERE ****
contentRepository.Save() 'Simply calls SubmitChanges()
Return View("ManagePages", pages)
End Function
GetAllContentPagesByType 返回 IQueryable - LINQ-to-SQL 查询的结果。该视图是强类型的:
Inherits="System.Web.Mvc.ViewPage(Of IQueryable (Of DBContent))"
我循环访问视图中的每个 DBContent 对象,并为一些属性创建文本框和其他输入 - 基本上我为模型中的每个记录显示一个编辑器。这很好用。
现在我尝试了许多不同的方法来更新它:
- 然后调用 UpdateModel() LINQ 数据上的 SubmitChanges() 上下文 - 什么也没做。
- 关注菲尔 Haack 的“绑定到列表”教程, 但它并没有深入到 更新模型: http://haacked.com/archive/2008 /10/23/model-binding-to-a-list.aspx
- 使用参数类型的变体 进入 ManagePages 的 HttpPost 中 没有用。
我现在能想到的让它工作的唯一方法是循环遍历 FormCollection 参数中的所有项目,并手动更新集合中的每个 DBContent 记录,但这似乎不是最佳实践解决方案。
问题是 - 在这种情况下更新任何可枚举类型的模型的黄金标准最佳实践是什么?
编辑
如果有帮助,这里是视图的代码片段。请注意,使用 Html.TextBox 等似乎不会影响生成的表单数据。我总是得到 4 个表单键,并用逗号分隔值(基本上每个属性一个)。我尝试在这些前面加上记录 ID(唯一键),但 UpdateModel() 仍然不起作用,尽管我确实为每个输入控件获得了唯一的表单值:
<% Using Html.BeginForm%>
<% For Each item In Model.OrderBy(Function(c) c.DisplayOrder)%>
<%: Html.Hidden("ContentId", Model.ContentId.ToString())%>
<tr>
<td class="first"><input name='Enabled' type="checkbox" checked='<%: If(Model.Enabled, "checked", "")%>' /></td>
<td class="first"><input name='DisplayOrder' type="text" value='<%: Model.DisplayOrder %>' style="width:40px" /></td>
<td class="first"><select name='ContentLevel'>
<option value="100" selected='<%: If(Model.ContentLevel = 100, "selected", "") %>'>Admin</option>
<option value="50" selected='<%: If(Model.ContentLevel = 50, "selected", "") %>'>Board</option>
<option value="25" selected='<%: If(Model.ContentLevel = 25, "selected", "") %>'>Member</option>
<option value="0" selected='<%: If(Model.ContentLevel = 0, "selected", "") %>'>Everyone</option>
</select></td>
<td><a href="EditPage/<%: Model.ContentId %>"><%: Model.PageTitle%></a></td>
<td><%: Model.aspnet_User.UserName%></td>
<td class="last"><%: Model.ModifiedOn%></td>
</tr>
<% Next%>
<% End Using%>
Controller Code:
Function ManagePages() As ActionResult
Dim pages = contentRepository.GetAllContentPagesByType("Content Page", False)
Return View("ManagePages", pages)
End Function
<HttpPost()> _
Function ManagePages(ByVal values As FormCollection) As ActionResult
Dim pages = contentRepository.GetAllContentPagesByType("Content Page", False)
''' **** HOW DO I UPDATE THE MODEL HERE ****
contentRepository.Save() 'Simply calls SubmitChanges()
Return View("ManagePages", pages)
End Function
GetAllContentPagesByType returns an IQueryable - the result of a LINQ-to-SQL query. The view is strongly typed:
Inherits="System.Web.Mvc.ViewPage(Of IQueryable (Of DBContent))"
I am looping through each of the DBContent objects in the view and creating textboxes and other inputs for a few properties - basically I am displaying an editor for each record in the Model. This works fine.
Now I've tried many different ways to get this to update:
- Calling UpdateModel() then
SubmitChanges() on the LINQ data
context - did nothing. - Followed Phil
Haack's "Binding to List" tutorial,
but it doesn't go in depth as far as
updating the model:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx - Used variations of parameter types
into the HttpPost for ManagePages to
no avail.
The only way I can think of now to get it to work would be to loop through all of the items in the FormCollection parameter, and manually update each DBContent record in the collection, but that doesn't seem like a best practice solution.
The question is - what is the gold standard best practice for this scenario to update a model of any enumerable type?
Edit
If it helps, here a code snippet for the view. Note that using Html.TextBox, etc, doesn't seem to affect the resulting form data. I'm always getting 4 form keys, with comma-separated values (one for each property basically). I've tried prepending these with the record ID (unique key), but UpdateModel() still doesn't work, though I do get a unique form value for each input control:
<% Using Html.BeginForm%>
<% For Each item In Model.OrderBy(Function(c) c.DisplayOrder)%>
<%: Html.Hidden("ContentId", Model.ContentId.ToString())%>
<tr>
<td class="first"><input name='Enabled' type="checkbox" checked='<%: If(Model.Enabled, "checked", "")%>' /></td>
<td class="first"><input name='DisplayOrder' type="text" value='<%: Model.DisplayOrder %>' style="width:40px" /></td>
<td class="first"><select name='ContentLevel'>
<option value="100" selected='<%: If(Model.ContentLevel = 100, "selected", "") %>'>Admin</option>
<option value="50" selected='<%: If(Model.ContentLevel = 50, "selected", "") %>'>Board</option>
<option value="25" selected='<%: If(Model.ContentLevel = 25, "selected", "") %>'>Member</option>
<option value="0" selected='<%: If(Model.ContentLevel = 0, "selected", "") %>'>Everyone</option>
</select></td>
<td><a href="EditPage/<%: Model.ContentId %>"><%: Model.PageTitle%></a></td>
<td><%: Model.aspnet_User.UserName%></td>
<td class="last"><%: Model.ModifiedOn%></td>
</tr>
<% Next%>
<% End Using%>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您根本不会调用 UpdateModel 来更新集合。
您需要按照此处的说明进行操作:
http://haacked.com/archive/2008 /10/23/model-binding-to-a-list.aspx
您的
元素名称属性需要遵循特定的语法才能正常工作。
You simply never make the call to UpdateModel to update the collection.
You need to follow the instructions here:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Your
<input>
elements name attributes need to follow a particular syntax for this to work.我最终按照 Phil Haack 的帖子,为每个控件指定了一个唯一的名称,以索引“[0.]”作为前缀。然后,我更改了 Action 方法以接受
List(of DBContent)
,它正确绑定了模型数据。然后,我可以手动循环遍历集合,并手动更新每条记录。I ended up going the route of giving each control a unique name, as per Phil Haack's post, starting with index "[0.]" as the prefix. I then changed my Action method to accept a
List(of DBContent)
, which correctly bound the model data. I was then able to manually loop through the collection, and manually update each record.