asp.net-mvc – MVC模型绑定:为什么我不能绑定到迭代器属性?
当我的模型具有IEnumerable< T>时实现为
iterator的属性(即yield return),当传入值使用方括号语法(例如“Foo [0]”)时,MVC的DefaultModelBinder无法绑定到该属性.
示例型号: namespace ModelBinderTest { using System.Collections.Generic; public class MyModel { private List<string> fooBacking = new List<string>(); public IEnumerable<string> Foo { get { foreach (var o in fooBacking) { yield return o; // <-- ITERATOR BREAKS MODEL BINDING } } set { fooBacking = new List<string>(value); } } private List<string> barBacking = new List<string>(); public IEnumerable<string> Bar { get { // Returning any non-iterator IEnumerable works here. Eg: return new List<string>(barBacking); } set { barBacking = new List<string>(value); } } } } 失败的例子1: namespace ModelBinderTest { using System; using System.Linq; using System.Web.Mvc; using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] [CLSCompliant(false)] public class DefaultModelBinderTestIterator { [TestMethod] public void BindsIterator() { // Arrange var model = new MyModel(); ModelBindingContext bindingContext = new ModelBindingContext() { FallbackToEmptyPrefix = true,ModelMetadata = ModelMetadataProviders .Current .GetMetadataForType(null,model.GetType()),ModelName = "",ValueProvider = new NameValueCollectionValueProvider( new System.Collections.Specialized.NameValueCollection() { { "Foo[0]","foo" },{ "Bar[0]","bar" },},System.Globalization.CultureInfo.InvariantCulture ) }; DefaultModelBinder binder = new DefaultModelBinder(); // Act MyModel updatedModel = (MyModel)binder.BindModel( new ControllerContext(),bindingContext); // Assert Assert.AreEqual(1,updatedModel.Bar.Count(),"Bar property should have been updated"); Assert.AreEqual("bar",updatedModel.Bar.ElementAtOrDefault(0),"Bar's first element should have been set"); Assert.AreEqual(1,updatedModel.Foo.Count(),"Foo property should have been updated"); Assert.AreEqual("foo",updatedModel.Foo.ElementAtOrDefault(0),"Foo's first element should have been set"); } } } 上面的单元测试会将我模型的Bar属性更新为[“bar”]没问题(在集合键中有或没有方括号),但是无法将任何内容绑定到Foo属性. 有没有人知道(在低级别)为什么实现IEnumerable属性作为迭代器会导致模型绑定失败? 我对workarounds2并不感兴趣,而是对一些分析感兴趣,因为我已经用尽了我对框架这方面的了解;) 1:单元测试是分离SO问题的最简单方法,而不是通过整个MVC应用程序示例. 2:例如,我知道如果我从输入中删除方括号并为所有值重用相同的“Foo”键,则模型绑定将起作用.然而,真正的失败案例需要方括号,因为集合中的每个项目都是具有自己的子属性的复杂类型.或者另一种解决方法:添加非迭代器IEnumerable< T>操作的参数,并将其直接分配给操作中的属性.啊. 解决方法
很简单,真的. DefaultModelBinder不会覆盖您的IEnumerable<>实例,如果它是非null.如果它为null,则它将创建一个新的List< T>并填写它.
如果它是非null,则它具有某些类型的列表,它知道如何处理.如果您的列表实现ICollection<>,那么它将填充它.但是你的实例(带有yield)根本无法更新! 如果您对覆盖foobacking感到满意,那么您可以通过编写自定义模型绑定器来解决这个问题. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – 构建时验证所有ASPX,ASCX和HTML文件
- asp.net-mvc – 如何处理MVC中的页面流(特别是asp.net)
- asp.net – 当我将’启用32位应用程序’更改为False时,为什
- asp.net – 是存储库单例或静态还是没有这些?
- asp.net – 未在生产服务器中的WCF调用上传递凭据
- 选择完成后和提交上传之前的asp.net FileUpload事件
- ASP.NET没有魔法——ASP.NET MVC IoC
- asp.net-mvc – 带有HTML5语义标记的MVC4项目HtmlHelper.Ed
- Asp.net MVC企业级开发(02)---Log4net
- asp.net-mvc – .net mvc仅当视图中有值时才在视图中显示