My DDD Value Objects don’t have default constructors. Neither do many of my entity objects — I like having my objects valid on instantiation. But ASP.NET’s DefaultModelBinder doesn’t know how to instantiate these objects. I created a ConstructorModelBinder to achieve this functionality. The code is below. Keep in mind that this will currently use the constructor with the most parameters.
You use it by specifying something like this in the Global.asax:
System.Web.Mvc.ModelBinders.Binders.Add(typeof(MyClass), new ConstructorModelBinder<MyClass>());
public class ConstructorModelBinder<T> : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
Type type1 = typeof(T);
ConstructorInfo[] constructors = type1.GetConstructors();
ConstructorInfo largestConstructor = constructors.OrderByDescending(x => x.GetParameters().Count()).First();
ParameterInfo[] parameters = largestConstructor.GetParameters();
List<object> paramValues = new List<object>();
IModelBinder binder;
string oldModelName = bindingContext.ModelName;
foreach (ParameterInfo param in parameters)
{
string name = CreateSubPropertyName(oldModelName, param.Name);
bindingContext.ModelType = param.ParameterType;
bindingContext.ModelName = name;
if (!System.Web.Mvc.ModelBinders.Binders.TryGetValue(param.ParameterType, out binder))
binder = System.Web.Mvc.ModelBinders.Binders.DefaultBinder;
object model = binder.BindModel(controllerContext, bindingContext);
paramValues.Add(model);
}
bindingContext.ModelType = typeof(T);
bindingContext.ModelName = oldModelName;
object obj = Activator.CreateInstance(type1, paramValues.ToArray());
return obj;
}
}