UPDATE: Я прошел через MVC исходного кода (особенно DefaultModelBinder
класс), и вот что я нашел:
Класс определяет, мы пытаемся связать коллекцию так он вызывает метод: UpdateCollection(...)
, который создает внутренний ModelBindingContext
, который имеет свойство null
Model
. Впоследствии этот контекст отправляется методу BindComplexModel(...)
, который проверяет свойство Model
для null
и создает экземпляр типа модели, если это так.
Это и вызывает сброс значений.
Таким образом, только значения, которые поступают через данные формы/запроса/данные маршрута, заполняются, остальное остается в его инициализированном состоянии.
Чтобы устранить эту проблему, я смог внести очень мало изменений в UpdateCollection(...)
.
Вот метод с моими изменениями:
internal object UpdateCollection(ControllerContext controllerContext, ModelBindingContext bindingContext, Type elementType) {
IModelBinder elementBinder = Binders.GetBinder(elementType);
// build up a list of items from the request
List<object> modelList = new List<object>();
for (int currentIndex = 0; ; currentIndex++) {
string subIndexKey = CreateSubIndexName(bindingContext.ModelName, currentIndex);
if (!DictionaryHelpers.DoesAnyKeyHavePrefix(bindingContext.ValueProvider, subIndexKey)) {
// we ran out of elements to pull
break;
}
// **********************************************************
// The DefaultModelBinder shouldn't always create a new
// instance of elementType in the collection we are updating here.
// If an instance already exists, then we should update it, not create a new one.
// **********************************************************
IList containerModel = bindingContext.Model as IList;
object elementModel = null;
if (containerModel != null && currentIndex < containerModel.Count)
{
elementModel = containerModel[currentIndex];
}
//*****************************************************
ModelBindingContext innerContext = new ModelBindingContext() {
Model = elementModel, // assign the Model property
ModelName = subIndexKey,
ModelState = bindingContext.ModelState,
ModelType = elementType,
PropertyFilter = bindingContext.PropertyFilter,
ValueProvider = bindingContext.ValueProvider
};
object thisElement = elementBinder.BindModel(controllerContext, innerContext);
// we need to merge model errors up
VerifyValueUsability(controllerContext, bindingContext.ModelState, subIndexKey, elementType, thisElement);
modelList.Add(thisElement);
}
// if there weren't any elements at all in the request, just return
if (modelList.Count == 0) {
return null;
}
// replace the original collection
object collection = bindingContext.Model;
CollectionHelpers.ReplaceCollection(elementType, collection, modelList);
return collection;
}
это тоже относится к MVC 3? – Vidar
@ Видар Да, боюсь. – nfplee