I'm 3 days into learning MVC for a new project and i've managed to stumble my way over the multitude of issues I've come across - mainly about something as simple as moving data to a view and back into the controller in a type-safe (and manageable) manner. This is the latest.
I've seen this reported before but nothing advised has seemed to work. I have a complex view model:
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; }
}
This maps to (the main Index page):
%@ 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>
and a 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>
This is returned to the following method:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Search(IndexViewModel viewModel)
{
....
}
My problem is that when the view model is rehydrated from the View into the ViewModel, the SearchFragment elements are null. I suspect this is because the default model binder doesn't realise the HTML ItemId and Identifier elements rendered inline in the View map to the SearchFragment class. When I have two extra properties (ItemId and Identifier) in the IndexViewModel, the values are bound correctly.
Unfortunately, as far as I can tell, I must use the SearchFragment as I need this to strongly type the Search UserControl... as the control can be used anywhere it can operate under any parent view.
I really don't want to make it use "magic strings". There's too much of that going on already IMO.
I've tried prefixing the HTML with "Search." in the hope that the model binder would recognise "Search.ItemId" and match to the IndexViewModel "Search" property and the ItemId within it, but this doesn't work.
I fear I'm going to have to write my own ModelBinder to do this, but surely this must be something you can do out-of-the-box??
Failing that is there any other suggestions (or link to someone who has already done this?)
Here's hoping....
Thanks so far. It's pretty obvious this fairly basic requirement is missing from MVC :p