I'm facing a problem ith a custom modelbinder.
I have two models (inheriting from a base class) that are displayed by EditorTemplates.
Base-Class:
public abstract class QuestionAnswerInputModel {
public Guid QuestionId {
get; set;
}
}
Modelclass 1:
public class RatingQuestionInputModel : QuestionAnswerInputModel{
[Required]
[Range(1,4)]
public int? Rating { get; set; }
}
Modelclass 2:
public class FreeTextQuestionInputModel: QuestionAnswerInputModel{
[Required]
public string FreeText { get; set; }
}
To get it bound I implemented a custom modelbinder:
public class QuestionAnswerModelBinder : DefaultModelBinder {
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
QuestionAnswerInputModel model;
if ((typeof(QuestionAnswerInputModel) != bindingContext.ModelType)) {
return null;
}
ModelBindingContext context = new ModelBindingContext(bindingContext);
Type typeOfModel;
string prefix = bindingContext.ModelName;
if (bindingContext.ValueProvider.ContainsPrefix(prefix + "." + new FreeTextQuestionInputModel().GetPropertyName(m => m.FreeText))) {
typeOfModel = typeof(FreeTextQuestionInputModel);
} else if (bindingContext.ValueProvider.ContainsPrefix(prefix + "." + new RatingQuestionInputModel().GetPropertyName(m => m.Rating))) {
typeOfModel = typeof(RatingQuestionInputModel);
} else {
return null;
}
context.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(), bindingContext.ModelMetadata.ContainerType, null, typeOfModel, bindingContext.ModelName);
return base.BindModel(controllerContext, context);
}
}
All in all it works great, BUT the values fpr properties of the models (QuestionId and Rating/Freetext) are not set? Can anyone tell me why? What am I doing wrong?
I also tried to call
new DefaultModelBinder().BindModel(controllerContext, context)
but the result is the same. Correctly instantiated objects but properties are not set.
UPDATE:
I now tried to override just the CreateModel-Methode of the DefaultBinder like in this post MVC 3 Model Binding a Sub Type (Abstract Class or Interface).
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) {
if ((typeof(QuestionAnswerInputModel) != bindingContext.ModelType)) {
return null;
}
string prefix = bindingContext.ModelName;
if (bindingContext.ValueProvider.ContainsPrefix(prefix + "." + new FreeTextQuestionInputModel().GetPropertyName(m => m.FreeText))) {
return new FreeTextQuestionInputModel();
} else if (bindingContext.ValueProvider.ContainsPrefix(prefix + "." + new RatingQuestionInputModel().GetPropertyName(m => m.Rating))) {
return new RatingQuestionInputModel();
} else {
return null;
}
}
The model is still instantiated correctly. The problem now is, that only the properties of the base class are set.
After some discussion with @macpak I found the solution. This works great for me:
I just have to override the CreateModel-Methode. Thanks to @MacPak!