包含列表的模型的TryUpdateModel将从模型中删除信息

时间:2011-12-15 22:33:30

标签: asp.net-mvc-3

我有一个很大的对象,我使用@Html.Serialize()进行序列化:

[Serializable]
public class ModelB
{
    public List<ModelA> ListOfModelA { get; set; }
    // more stuff
}

此对象包含一个包含多个属性的类的对象列表。其中一些我将它们包含在我的视图中,而另一些我甚至懒得把它们作为隐藏字段,就像我在序列化模型中一样。

[Serializable]
public class ModelA
{
    public string StringA { get; set; }
    public string StringB { get; set; }
    // more stuff
    public string HiddenStringA { get; set; }
    public string HiddenStringB { get; set; }  
    // more stuff
}

现在,当我使用我的更改回发表单时,我会重新构建我的模型,然后使用从表单中获取的值字典更新它。

[HttpPost]
public ActionResult Edit([Deserialize] ModelTwo model,
                         FormCollection form)
{
    TryUpdateModel(model, form.ToValueProvider());

    // more stuff
}

我介入我的代码,就在我进行更新之前,我看到我的反序列化模型包含一个ListOfModelA列表,而ListOfModelA又包含应该存在的所有元素,在其中我可以看到所有HiddenStringA和HiddenStringB属性。然后我偷看表格,我看到一个字典,上面有这样的键:

ListOfModelA[0].StringA 
ListOfModelA[0].StringB
ListOfModelA[1].StringB
ListOfModelA[1].StringB

虽然没有其他属性的键,如下所示:

ListOfModelA[0].HiddenStringA

接下来,我再向前迈进一步,让代码执行TryUpdateModel。现在,查看ListOfModelA属性,所有元素都被替换为所有隐藏值为null的元素。就好像更新重建了整个元素(它具有有限的信息),而不是只更新它拥有信息的属性。

这是预期的行为吗?有没有办法保留我的模型,只更新字典中有键的属性?

谢谢,

帕诺斯

1 个答案:

答案 0 :(得分:0)

我的问题比上面描述的问题更复杂,但是我为特定设计找到的解决方案大致如下。我序列化作为列表的模型部分,并通过操作的参数绑定整个模型。这样我就避免使用TryUpdateModel,虽然这不是导致我麻烦的原因。然后,我从表单创建的模型中将非空值注入到反序列化模型中,最后我将后者的相应部分指向前者。

[HttpPost]
public ActionResult Edit(ModelTwo model,
                         [Deserialize] List<ModelA> serializedList)
{
    serializedList.InjectFrom<NonNullLoopValueInjection>(model.ListOfModelA);
    model.ListOfModelA = serializedList;

    // more stuff
}

对于注射,我使用Value Injecter,其中NonNullLoopValueInection定义如下

public class NonNullLoopValueInjection : LoopValueInjection
{
    protected override bool AllowSetValue(object value)
    {
        return value != null;
    }
}

也许不是最好的设计,但它有效,它可能会让我更好。任何反馈都非常受欢迎。