MVC вызывает привязку модели непосредственно к одному объекту - PullRequest
8 голосов
/ 29 сентября 2011

Есть ли способ, которым я могу вызвать связыватель модели для одного объекта?

Мне не нужно / не нужно настраивать связыватель модели - я просто хочу сделать что-то вроде этого:

MyViewModel1 vModel1 = new MyViewModel1();
InvokeModelBinder(vModel1);

MyViewModel2 vModel2= new MyViewModel2();
InvokeModelBinder(vModel2);

И когда я закончу, свойства vModel1 и vModel2 были привязаны к тому, что во входящем запросе. Из-за того, как пишется наш контроллер / действие, я не обязательно хочу перечислять vModel1 и vModel2 во входном списке метода действия (поскольку в конечном итоге будет потенциально длинный список моделей представлений, с которыми можно связываться).

Ответы [ 2 ]

8 голосов
/ 01 октября 2013

Использование Controller.UpdateModel :

MyViewModel1 vModel1 = new MyViewModel1();
UpdateModel(vModel1);

Обновление

Обратите внимание, что если ModelState в контроллере есть ошибки проверки (связанные с моделью, переданной в действии), UpdateModel (с любой моделью) выдает исключение, несмотря на успех UpdateModel и обновление vModel1. Поэтому ошибки в ModelState следует удалить или поместить UpdateModel в try / catch и просто игнорировать исключение

2 голосов
/ 29 сентября 2011

Это неправильно на многих уровнях ИМХО:

  1. Это не то, как ASP.NET MVC предназначен для работы.
  2. Ваши действия не определяют четкий контракт о том, какие данные они ожидают.
  3. Что вы получаете от этого?Пахнет как плохой дизайн.

Привязка модели обусловлена ​​отражением.Перед вызовом действия он отобразит список параметров метода и для каждого объекта и его свойств вызовет связыватель модели, чтобы найти значение для каждого свойства от различных поставщиков значений (поставщик значений POST, параметры URL и т. Д.).Во время привязки модели также выполняется валидация ModelState.

Поэтому, не используя для этого ASP.NET MVC по умолчанию, вы теряете все это.

Даже если бы вам пришлось вручную удерживатьсвязывателя модели, подобного этому:

IModelBinder modelBinder = ModelBinders.Binders.GetBinder(typeof(MyObject));
MyObject myObject = (MyObject ) modelBinder.BindModel(this.ControllerContext, ** ModelBindingContext HERE**);

Вы можете видеть, что вам нужно инициализировать ModelBindingContext, то, что ASP.NET MVC будет делать внутренне на основе текущего свойства, которое он отражает.Вот фрагмент исходного кода ASP.NET MVC:

protected virtual object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) {
// collect all of the necessary binding properties
Type parameterType = parameterDescriptor.ParameterType;
IModelBinder binder = GetModelBinder(parameterDescriptor);
IDictionary<string, ValueProviderResult> valueProvider = controllerContext.Controller.ValueProvider;
string parameterName = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName;
Predicate<string> propertyFilter = GetPropertyFilter(parameterDescriptor);

// finally, call into the binder
ModelBindingContext bindingContext = new ModelBindingContext() {
    FallbackToEmptyPrefix = (parameterDescriptor.BindingInfo.Prefix == null), // only fall back if prefix not specified
    ModelName = parameterName,
    ModelState = controllerContext.Controller.ViewData.ModelState,
    ModelType = parameterType,
    PropertyFilter = propertyFilter,
    ValueProvider = valueProvider
};
object result = binder.BindModel(controllerContext, bindingContext);
return result;

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...