我在为一个新项目学习MVC已经有3天了,我已经成功地遇到了我遇到的众多问题 - 主要是关于将数据移动到视图并返回到控制器以类型安全(和可管理)的方式。这是最新的。
我以前见过这个报道,但没有任何建议似乎有效。我有一个复杂的视图模型:
public class IndexViewModel : ApplicationViewModel
{
public SearchFragment Search { get; private set; }
public IndexViewModel()
{
this.Search = new SearchFragment();
}
}
public class SearchFragment
{
public string ItemId { get; set; }
public string Identifier { get; set; }
}
这映射到(主索引页面):
%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IndexViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<% Html.BeginForm("Search", AvailableControllers.Search, FormMethod.Post); %>
<div id="search">
<% Html.RenderPartial("SearchControl", Model.Search); %>
</div>
<% Html.EndForm(); %>
</asp:Content>
和UserControl:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SearchFragment>" %>
<p>
<label for="itemId">
<%= Html.Resource("ItemId") %></label>
<%= Html.TextBox("itemId", Model.ItemId)%>
</p>
<p>
<label for="title">
<%= Html.Resource("Title") %></label>
<%= Html.TextBox("identifier", Model.Identifier)%>
</p>
<p>
<input type="submit" value="<%= Html.Resource("Search") %>" name="search" />
</p>
这将返回到以下方法:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Search(IndexViewModel viewModel)
{
....
}
我的问题是,当视图模型从View重新水化为ViewModel时,SearchFragment元素为null。我怀疑这是因为默认模型绑定器没有实现在SearchFragment类的View映射中内联呈现的HTML ItemId和Identifier元素。当我在IndexViewModel中有两个额外的属性(ItemId和Identifier)时,这些值被正确绑定。
不幸的是,据我所知,我必须使用SearchFragment来强烈输入Search UserControl ...因为控件可以在任何父视图下运行的任何地方使用。
我真的不想让它使用“魔术字符串”。 IMO已经有太多的事情发生了。
我尝试使用“搜索”为HTML添加前缀。希望模型绑定器能够识别“Search.ItemId”并匹配IndexViewModel“搜索”属性和其中的ItemId,但这不起作用。
我担心我必须编写自己的ModelBinder才能做到这一点,但这肯定是你可以开箱即用的东西吗?
如果没有其他建议(或链接到已经完成此操作的人?)
这是希望......
到目前为止,谢谢。很明显,MVC缺少这个相当基本的要求:p
答案 0 :(得分:1)
我认为您的问题可能就在这里:
public IndexViewModel()
{
this.Search = new SearchFragment();
}
您是否尝试将Search属性保留为null?我知道DefaultModelBinder中的CreateModel受保护方法不会触发,除非该值已经为null,但我不确定是否设置了属性。如果你还没有尝试过那就试一试......
修改强>
我刚注意到:
<%= Html.TextBox("identifier", Model.Identifier)%
应该是:
<%= Html.TextBox("Search.Identifier", Model.Identifier)%
答案 1 :(得分:0)
也许您应该尝试将操作方法更改为类似的方法并手动执行绑定:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Search(FormCollection formCollection)
{
var viewModel = new IndexViewModel();
viewModel.Search.ItemId = formCollection[0];
viewModel.Search.Identifier = formCollection[1];
...
}
但这种方法有点类似于创建自己的活页夹。
答案 2 :(得分:0)
我的第一个想法是SearchFragment的属性与表单字段的情况不同。
我可能错了,但可能值得一试。
修改强>:
在进一步的调查中,您可能还需要考虑表单使用SearchFragment但View使用IndexViewModel的事实 - 为什么不使用SearchFragment作为ViewModel?