当请求中没有属性时的DefaultModelBinder行为

时间:2011-08-02 15:22:57

标签: c# asp.net-mvc asp.net-mvc-3 model-binding

我有一个如下模型:

public class TestViewModel
{
  string UpdateProperty { get; set; }
  string IgnoreProperty { get; set; }
  ComplexType ComplexProperty { get; set; }
}

,其中

public class ComplexType
{
  long? Code { get; set; }
  string Name { get; set; }
}

我的控制器操作:

public Edit(int id, FormColleciton formCollection)
{
  var model = service.GetModel(id);
  TryUpdateModel(model);

  //...
}

调用Edit操作时,我有一个formCollection参数,只包含UpdateProperty的键/值。

在正确设置TryUpdateModel UpdateProperty调用后,IgnoreProperty保持未被触摸但ComplexProperty设置为null,即使它之前有值。

TryUpdateModel()是否应仅修改属于请求的属性?如果不是这种情况,解决此问题的最佳方法是什么,只有在请求中包含ComplexProperty时才会修改它?


在Darin指出上面的测试用例没有证明问题之后我添加了一个真正发生这个问题的场景:

public class TestViewModel
{
    public List<SubModel> List { get; set; }
}

public class SubModel
{
    public ComplexType ComplexTypeOne { get; set; }
    public string StringOne { get; set; }
}

public class ComplexType
{
    public long? Code { get; set; }
    public string Name { get; set; }
}

控制器操作:

public ActionResult Index()
{
    var model = new TestViewModel
                    {
                        List = new List<SubModel> { 
                            new SubModel{
                                ComplexTypeOne = new ComplexType{Code = 1, Name = "5"},
                                StringOne = "String One"
                            } 
                        }
                    }; 

    if (TryUpdateModel(model)) { } 

    return View(model);
}

发送此请求:

/Home/Index?List[0].StringOne=test

更新SubModel.StringOne属性,但将ComplexTypeOne设置为null,即使它未包含在请求中。

这是预期的行为(除非使用了许多复杂类型,否则不会发生这种情况)?如何最好地解决这个问题?

1 个答案:

答案 0 :(得分:1)

您的测试用例一定有问题,因为我无法重现它。这是我试过的:

模型(注意我使用公共属性):

public class TestViewModel
{
    public string UpdateProperty { get; set; }
    public string IgnoreProperty { get; set; }
    public ComplexType ComplexProperty { get; set; }
}

public class ComplexType
{
    public long? Code { get; set; }
    public string Name { get; set; }
}

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new TestViewModel
        {
            IgnoreProperty = "to be ignored",
            UpdateProperty = "to be updated",
            ComplexProperty = new ComplexType
            {
                Code = 1,
                Name = "5"  
            }
        };

        if (TryUpdateModel(model))
        {

        }
        return View();
    }
}

现在我发送以下请求:/home/index?UpdateProperty=abc并且在条件内仅使用查询字符串中的新值修改UpdateProperty。所有其他属性,包括复杂属性,都保持不变。

另请注意,FormCollection操作参数无用。