Thứ Sáu, 14 tháng 1, 2011

ASP.NET MVC: naming convention when using custom ViewModel

If you are going to use custom ViewModel (complex Model) in ASP.NET MVC 2, you may always get a null Returns in Form when call Html.EditorFor(p => p.PageContent) If you review ASP.NET MVC 2 BindModel() Source, you see:

public virtual object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
if (bindingContext == null) {
throw new ArgumentNullException("bindingContext");
}

bool performedFallback = false;

if (!String.IsNullOrEmpty(bindingContext.ModelName) && !DictionaryHelpers.DoesAnyKeyHavePrefix(bindingContext.ValueProvider, bindingContext.ModelName)) {
// We couldn't find any entry that began with the prefix. If this is the top-level element, fall back
// to the empty prefix.
if (bindingContext.FallbackToEmptyPrefix) {
bindingContext = new ModelBindingContext() {
Model = bindingContext.Model,
ModelState = bindingContext.ModelState,
ModelType = bindingContext.ModelType,
PropertyFilter = bindingContext.PropertyFilter,
ValueProvider = bindingContext.ValueProvider
};
performedFallback = true;
}
else {
return null;
}
}

// Simple model = int, string, etc.; determined by calling TypeConverter.CanConvertFrom(typeof(string))
// or by seeing if a value in the request exactly matches the name of the model we're binding.
// Complex type = everything else.
if (!performedFallback) {
ValueProviderResult vpResult;
bindingContext.ValueProvider.TryGetValue(bindingContext.ModelName, out vpResult);
if (vpResult != null) {
return BindSimpleModel(controllerContext, bindingContext, vpResult);
}
}
if (TypeDescriptor.GetConverter(bindingContext.ModelType).CanConvertFrom(typeof(string))) {
return null;
}

return BindComplexModel(controllerContext, bindingContext);
}

The Controller action I defined to hand Create action

public ActionResult Create(EnterpriseSearch seach)

Thus causing the DefaultModelBinder find the Search model then it is not match with EnterpriseSearch model => search property always null.


So, your have to change your Create action like this (Model name and parameter name is the same characters: EnterpriseSearch enterpriseSearch)

public ActionResult Create(EnterpriseSearch enterpriseSearch)