Custom Model Binder does not fire
asp.net-mvc-4, c#, model-binding
Solution
Model binders are used to allow actions to accept complex object types as parameters. These complex types should be generated via POST requests, for example, by submitting a form. If you have a highly complex object that cannot be binded by the default model binder (or it wouldn't be effective), you can use custom model binders.
To answer your question: if you don't add a custom model binder for the `MyListWrapper` class too, the BindModel(of the `MyListBinder)`won't be called in a GET request, this is how ASP.NET MVC works. However, if you modify your code by adding a POST action with the `MyListWrapper` parameter, you can see that the BindModel method is called properly.
[HttpGet]
public ActionResult Index2() // ModelBinder doesn't fire
{
return View();
}
[HttpPost]
public ActionResult Index2(MyListWrapper wrapper) // ModelBinder fires
{
return View();
}
And the Index2 view
@model fun.web.MyListWrapper
@using (Html.BeginForm())
{
@Html.HiddenFor(m => m.listItems)
<input type="submit" value="Submit" />
}
If you'd like "control" the action parameters in a GET request, you should use action filters.
Problem
I have registered a custom model binder for MyList in global.asax. However the model binder does not fire for nested properties, for simple types it works fine. In the example below, it fires for Index() but not does not fire for Index2() Global.asax ``` protected void Application_Start() { AreaRegistration.RegisterAllAreas(); ModelBinders.Binders.Add(typeof(MyList), new MyListBinder()); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); } ``` Code: ``` public class MyListBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { return new MyList(); } } public class MyList { public List<int> items { get; set; } } public class MyListWrapper { public MyList listItems { get; set; } } public class TestController : Controller { public ActionResult Index(MyList list) // ModelBinder fires :-) { return View(); } public ActionResult Index2(MyListWrapper wrapper) // ModelBinder does not fire! :-( { return View(); } } ```