我不确定这是否是DefaultModelBinder类中的错误或者是什么.
但UpdateModel通常不会更改模型的任何值,除了它找到匹配的值.
看看以下内容:
但UpdateModel通常不会更改模型的任何值,除了它找到匹配的值.
看看以下内容:
[AcceptVerbs(HttpVerbs.Post)] public ViewResult Edit(List<int> Ids) { // Load list of persons from the database List<Person> people = GetFromDatabase(Ids); // shouldn't this update only the Name & Age properties of each Person object // in the collection and leave the rest of the properties (e.g. Id,Address) // with their original value (whatever they were when retrieved from the db) UpdateModel(people,"myPersonPrefix",new string[] { "Name","Age" }); // ... }
会发生什么是UpdateModel创建新的Person对象,分配他们的名称&来自ValueProvider的Age属性并将它们放在参数List<>中,这使得其余属性设置为其默认初始值(例如Id = 0)
那么这里发生了什么?
解决方法
更新:
我介绍了mvc源代码(特别是DefaultModelBinder类),这是我发现的:
我介绍了mvc源代码(特别是DefaultModelBinder类),这是我发现的:
该类确定我们正在尝试绑定一个集合,因此它调用方法:UpdateCollection(…),它创建一个具有null Model属性的内部ModelBindingContext.然后,将该上下文发送到方法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;
}