Writing a custom binder looks like a good idea here:
public class TimeSpanModelBinder : DefaultModelBinder { public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".TotalMinutes"); int totalMinutes; if (value != null && int.TryParse(value.AttemptedValue, out totalMinutes)) { return TimeSpan.FromMinutes(totalMinutes); } return base.BindModel(controllerContext, bindingContext); } }
And registering it in Application_Start :
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterRoutes(RouteTable.Routes); ModelBinders.Binders.Add(typeof(TimeSpan), new TimeSpanModelBinder()); }
And finally, always prefer strongly typed helpers in your opinion:
<% using (Html.BeginForm()) { %> <%= Html.EditorFor(x => x.Interval) %> <input type="submit" value="OK" /> <% } %>
And the corresponding editor template ( ~/Views/Home/EditorTemplates/TimeSpan.ascx ):
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<TimeSpan>" %> <%= Html.EditorFor(x => x.TotalMinutes) %>
Now your controller can be as simple as:
public class HomeController : Controller { public ActionResult Index() { var model = new MyViewModel { Interval = TimeSpan.FromDays(1) }; return View(model); } [HttpPost] public ActionResult Index(MyViewModel model) {
Darin Dimitrov
source share