I create several custom binders for complex types in my model. My model consists of objects that have their own binders. I want the base object to do its dirty work, and then populate the complex object that it encapsulates, passing standard ModelBinder routing. How to do it?
For illustration purposes, I created a very simple example.
Say my model contains these objects.
public class Person
{
public string Name {get; set;}
public PhoneNumber PhoneNumber {get; set;}
}
public class PhoneNumber
{
public string AreaCode {get; set;}
public string LocalNumber {get; set;}
}
And I have the following Binders for each of these models. It’s not that PersonBinder needs to fill in PhoneNumber, but doesn’t want to duplicate code in PhoneNumber bundle. How to delegate this back to the routing of the Stardard Binder?
public class PersonBinder: IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
Person person = new Person();
person.Name = bindingContext.ValueProvider.GetValue(String.Format("{0}.{1}", bindingContext.ModelName, "Name")).AttemptedValue
person.PhoneNumber = ???;
return person;
}
}
public class PhoneNumberBinder: IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
PhoneNumber phoneNumber = new PhoneNumber();
phoneNumber.AreaCode = bindingContext.ValueProvider.GetValue(String.Format("{0}.{1}", bindingContext.ModelName, "AreaCode")).AttemptedValue
phoneNumber.LocalNumber = bindingContext.ValueProvider.GetValue(String.Format("{0}.{1}", bindingContext.ModelName, "LocalNumber")).AttemptedValue
return phoneNumber;
}
}
And of course, I registered my ModelBinders in the Global.asax.cs file.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ModelBinders.Binders[typeof(Person)] = new PersonBinder();
ModelBinders.Binders[typeof(PhoneNumber)] = new PhoneNumberBinder();
}
Thank,
Justin