当我尝试使用这两个属性绑定模型时,我在模型绑定期间遇到错误:
private IEnumerable<Claimant> _drivers;
public IEnumerable<Claimant> Drivers
{
get
{
return _drivers ?? Enumerable.Empty<Claimant>();
}
set
{
_drivers = value;
}
}
private IEnumerable<Property> _vehicles;
public IEnumerable<Property> Vehicles
{
get
{
return _vehicles ?? Enumerable.Empty<Property>();
}
set
{
_vehicles = value;
}
}
错误:
System.Reflection.TargetInvocationException was unhandled by user code
Message=Exception has been thrown by the target of an invocation.
Source=mscorlib
StackTrace:
<snip>
InnerException: System.NotSupportedException
Message=Collection is read-only.
Source=mscorlib
StackTrace:
at System.SZArrayHelper.Clear[T]()
at System.Web.Mvc.DefaultModelBinder.CollectionHelpers
.ReplaceCollectionImpl[T](ICollection`1 collection, IEnumerable newContents)
InnerException:
如果我将属性更改为基本自动属性:
public IEnumerable<Claimant> Drivers { get; set; }
public IEnumerable<Property> Vehicles { get; set; }
一切正常。
当setter与auto属性setter相同时,为什么模型绑定会出现问题?
修改 - 通过default model binder source阅读最终会引导您进入此行,第一行是针对该属性调用Clear()
,所以当我退回了Empty<T>
它显然无法正常工作。
private static void ReplaceCollectionImpl<T>(ICollection<T> collection, IEnumerable newContents)
{
collection.Clear();
if (newContents != null)
{
foreach (object item in newContents)
{
// if the item was not a T, some conversion failed. the error message will be propagated,
// but in the meanwhile we need to make a placeholder element in the array.
T castItem = (item is T) ? (T)item : default(T);
collection.Add(castItem);
}
}
}
答案 0 :(得分:6)
试试这样:
get
{
return _drivers ?? new List<Claimant>();
}
答案 1 :(得分:5)
IIRC Enumerable.Empty<T>
是一个静态的只读枚举,用于将可枚举的空存储器无法传递给方法。它并不意味着用作空集合的“起点”。这可能是你收到错误的原因。
选择存储机制(例如List<T>
)并将其用作支持字段的类型。然后你可以初始化它
的示例:
private List<Claimant> _drivers = new List<Claimamt>(); // Option 1
public MyModel()
{
_drivers = new List<Claimant>(); // Option 2
}
public IEnumerable<Claimant> Drivers
{
get
{
return _drivers ?? (_drivers = new List<Claimant>()); // Option 3
}
set
{
_drivers = value;
}
}
答案 2 :(得分:1)
在自定义getter中,我通常会看到用于在返回时设置私有后备字段的空合并运算符(??):
private IEnumerable<Claimant> _drivers;
public IEnumerable<Claimant> Drivers
{
get
{
return _drivers ?? (_drivers = Enumerable.Empty<Claimant>());
}
set
{
_drivers = value;
}
}
您也可以尝试将默认值设置为空数组:
(_drivers = new Claimant[]{})
答案 3 :(得分:1)
找出导致问题的确切属性名称和类型:
public class TestBinder: DefaultModelBinder
{
public override object BindModel(
ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
Debug.WriteLine(bindingContext.ModelName);
Debug.WriteLine(bindingContext.ModelType.ToString());
//HOW TO USE: Look at your Output for the most recently output ModelName and Type to determine where there problem lies
return base.BindModel(controllerContext, bindingContext);
}
}
将此活页夹设为默认值:
ModelBinders.Binders.DefaultBinder = new TestBinder();