Привязка модели ASP.NET к базовому типу
У меня есть BaseViewModel, все мои модели просмотра наследуются.
public class MagazineViewModel : BaseOutputViewMode
{
public string TitleOfPublication { get; set; }
}
В моем контроллере я использую фабричный метод, чтобы вернуть корректную модель представления на основе входных данных:
// e.g. viewModel contains an instance of MagazineViewModel
BaseOutputViewModel viewModel = BaseOutputViewModel.GetOutputViewModel(output);
Когда я использую TryUpdateModel, чтобы попытаться привязать к коллекции FormCollection, которая, как мне известно, содержит ключ "TitleOfPublication", он никогда не устанавливается в моей модели представления:
if (!TryUpdateModel(viewModel, form))
Я думаю, что это как-то связано с DefaultModelBinder, использующим BaseOutputViewModel для привязки ключей FormCollection к - он не содержит "TitleOfPublication", как это делает производный MagazineViewModel.
Я пытаюсь свернуть свой собственный механизм связывания, чтобы переопределить поведение BindModel DefaultModelBinder. Все подключено правильно, и я могу отладить его сразу после вызова TryUpdateModel:
public class TestModelBinder : DefaultModelBinder, IFilteredModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
// Tried the following without success ....
// 1. Quick hardcoded test
// bindingContext.ModelType = typeof(MagazineViewModel);
// 2. Set ModelMetadata, hardcoded test again
// bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(MagazineViewModel));
// 3. Replace the entire context
// ModelBindingContext context2 = new ModelBindingContext();
// context2.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(MagazineViewModel));
// context2.ModelName = bindingContext.ModelName;
// context2.ModelState = bindingContext.ModelState;
// context2.ValueProvider = bindingContext.ValueProvider;
// bindingContext = context2;
}
}
Но я не уверен, как работать с bindingContext? Что необходимо обновить, чтобы я мог указать DefaultModelBinder связываться, используя производные свойства View Model? Или я просто совершенно неправильно понял это!
Я действительно пытался переопределить CreateModel - очень похоже на DerivedTypeModelBinder в MvcContrib, но я думаю, что, поскольку я даю связующему экземпляр модели для работы, CreateModel никогда не вызывается. Используется Reflector в Mvc DLL, есть "BindComplexModel", которая вызывает CreateModel, только если модель является нулевой:
if (model == null)
{
model = this.CreateModel(controllerContext, bindingContext, modelType);
}
Любые указатели с благодарностью получены!
ура
1 ответ
ОК - наконец дошли до сути этого! На самом деле с моим механизмом связывания ничего плохого не было, проблема в конечном итоге привела к появлению пары входных тегов, которые не имели имени / идентификатора:
<input id="" name="" type="text">
Суть этого теста была в DefaultModelBinder:
// 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.GetValue(bindingContext.ModelName);
if (vpResult != null) {
return BindSimpleModel(controllerContext, bindingContext, vpResult);
}
}
Без идентификатора / имени коллекция форм имеет ключ "", что означает, что GetValue правильно вернул значение для этого поля, продолжая связываться как простая модель.
Когда добавляются идентификатор / имя, коллекция форм не содержит ключа "" (который теперь является именем моей модели, поскольку мы используем TryUpdateModel). Это означало, что DefaultModelBinder правильно рассматривал мою модель как комплекс, успешно связывающий свойства в моем производном типе!
ура