Controller.UpdateModel<TModel>(TModel model, ...) 函数族只绑定定义在 TModel 及其基类中定义的属性,而不绑定 TModel 的派生类中定义的属性。
例如:
public class MyBase
{
public String Foo { get; set; }
}
public class MyDerived : MyBase
{
public String Bar { get; set; }
}
public class MyController : Controller
{
public void Search(FormCollection values)
{
MyBase obj = new MyDerived(); //有时我们会根据values的值来决定创建哪个类型的实例
UpdateModel(obj, values);
Assert.AreEqual( " foo ", obj.Foo);
Assert.AreNotEqual( " bar ", ((MyDerived)obj).Bar);
}
}
[TestFixture]
public class UpdateModelTests
{
[Test]
public void Test()
{
FormCollection values = new FormCollection();
values.Add( " Foo ", " foo ");
values.Add( " Bar ", " bar ");
MyController c = new MyController();
c.ControllerContext = new ControllerContext();
c.Search(values);
}
}
public String Foo { get; set; }
}
public class MyDerived : MyBase
{
public String Bar { get; set; }
}
public class MyController : Controller
{
public void Search(FormCollection values)
{
MyBase obj = new MyDerived(); //有时我们会根据values的值来决定创建哪个类型的实例
UpdateModel(obj, values);
Assert.AreEqual( " foo ", obj.Foo);
Assert.AreNotEqual( " bar ", ((MyDerived)obj).Bar);
}
}
[TestFixture]
public class UpdateModelTests
{
[Test]
public void Test()
{
FormCollection values = new FormCollection();
values.Add( " Foo ", " foo ");
values.Add( " Bar ", " bar ");
MyController c = new MyController();
c.ControllerContext = new ControllerContext();
c.Search(values);
}
}
解决方案:
自己构建一个 TryUpdateModel(Object model, ...) 函数,代码可以用 reflector 或者 dotPeek 或者 reSharper 从MVC的类库中复制过来, 并更改
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, typeof(TModel)),
为
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()),