Привязка модели 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 для привязки с использованием свойств производной модели представления? Или я просто неправильно понял это!

Я попытался переопределить CreateModel - так же, как DerivedTypeModelBinder в MvcContrib, но я думаю, что, поскольку я даю связывателю экземпляр модели для работы, CreateModel никогда не вызывается. Используемый Reflector в Mvc DLL, есть "BindComplexModel", который вызывает CreateModel, только если модель имеет значение NULL:

if (model == null)
{
    model = this.CreateModel(controllerContext, bindingContext, modelType);
}

Любые указатели были приняты с удовольствием!

Ваше здоровье


person Neil    schedule 31.10.2010    source источник


Ответы (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 правильно обработал мою модель как сложную, успешно связывающую свойства в моем производном типе!

Ваше здоровье

person Neil    schedule 01.11.2010