调用的UpdateModel具有复杂数据类型的集合重置所有非绑定值?(Calling UpdateM

2019-06-17 20:29发布

我不知道这是否是在DefaultModelBinder类或什么的错误。 但通常的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转让他们的姓名和年龄属性,并把它们在参数列表<>,这使得设置为默认的初始值的属性的其余部分(如ID = 0),那么是什么会在这里?

Answer 1:

更新:我通过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;

}



Answer 2:

鲁迪Breedenraed只是写了一个很好的职位描述这个问题,也是一个非常有用的解决方案。 他覆盖DefaultModelBinder,然后当它遇到一个集合更新,它实际上更新的项目,而不是创建新的它像默认的MVC行为。 有了这个,的UpdateModel()和TryUpdateModel()行为是与两个根模型和任何集合一致。



Answer 3:

你只给我一个想法,挖掘到ASP.NET MVC 2的源代码。 我一直在挣扎这两周。 我发现,您的解决方案将不会与嵌套列表的工作。 我把一个断点在UpdateCollection方法,它从来没有被击中。 这似乎是模式的根级别必须是一个列表被调用此方法

这是短期的模型我也have..I有泛型列表中多了一个层次,但是这仅仅是一个快速的样品..

public class Borrowers
{
   public string FirstName{get;set;}
   public string LastName{get;set;}
   public List<Address> Addresses{get;set;}
}

我想,我需要深入挖掘,找出到底是怎么回事。

工程进展:UpdateCollection仍然被称为在asp.net MVC 2,但与修订以上是有关这个问题HERE



文章来源: Calling UpdateModel with a collection of complex data types reset all non-bound values?