views:

29

answers:

0

I have a complex type composed of two nullable DateTimes:

public class Period
{
    public DateTime? Start { get; set; }
    public DateTime? End { get; set; }

    public static implicit operator string(Period period) { /* converts from Period to string */ }
    public static implicit operator Period(string value) { /* and back again */ }
}

I want to display them together in a single textbox as a date range so I can provide a nice jQuery UI date range selector. To make that happen have the following custom editor template:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Period>" %>

<% string name = ViewData.TemplateInfo.HtmlFieldPrefix; %>
<%= Html.PeriodTextBox(name, Model.EarliestDate, Model.LatestDate) %>

Where Html.PeriodTextBox is an extension method I've written that just concatenates the two dates sensibly, turns off autocomplete and generates a textbox, like so:

public static MvcHelperString PeriodTextBox(this HtmlHelper helper, string name, DateTime? startDate, DateTime? endDate)
{
    TagBuilder builder = new TagBuilder("input");
    builder.GenerateId(name);
    builder.Attributes.Add("name", name);
    builder.Attributes.Add("type", "text");
    builder.Attributes.Add("autocomplete", "off");

    builder.Attributes.Add("value", ConcatDates(startDate, endDate));

    return MvcHtmlString.Create(builder.ToString());
}

That's working fine in that I can call <%= Html.EditorFor(m => m.ReportPeriod) %> and I get my textbox, then when the form is submitted the FormCollection passed to the post action will contain an entry named ReportPeriod with the correct value.

[HttpPost]
public ActionResult ReportByRange(FormCollection formValues)
{
    Period reportPeriod = formValues["ReportPeriod"]; // creates a Period, with the expected values
}

The problem is if I replace the FormCollection with the model type I'm passing to the view then the ReportPeriod property never gets set.

[HttpPost]
public ActionResult ReportByRange(ReportViewModel viewModel)
{
    Period reportPeriod = viewModel.ReportPeriod; // this is null
}

I expected MVC would try to set the string from the textbox to that property and it would automatically generate a Period (as in my FormCollection example), but it's not.

How do I tell the textbox I've generated in the custom editor to poplate that property on the model?