mvvm 绑定字典集合
Levi Broderick, a Senior Developer on ASP.NET MVC and all around smart dude, posted some details to an internal Microsoft mailing list today and I thought it was worth sharing. Levi agreed and I've expanded on it some. Phil blogged some about Model Binding to a List last October.
Levi Broderick是ASP.NET MVC和智能花花公子的高级开发人员,今天在Microsoft内部邮件列表中发布了一些详细信息,我认为值得分享。 Levi同意了,我对此做了一些扩展。 Phil去年10月在博客中写了一些关于“模型绑定到列表”的文章。
The default model binder will handle a number of collection types for you, if you play by the rules and make your HTML form elements follow a certain format.
如果您遵守规则并使HTML表单元素遵循某种格式,则默认的模型绑定器将为您处理多种集合类型。
If the method signature looks like this:
如果方法签名如下所示:
public ActionResult Blah(Person[] people) {
// ...
}
And we are given this input in our HTML:
我们在HTML中得到以下输入:
<input type="text" name="people[0].FirstName" value="George" />
<input type="text" name="people[0].LastName" value="Washington" />
<input type="text" name="people[1].FirstName" value="Abraham" />
<input type="text" name="people[1].LastName" value="Lincoln" />
<input type="text" name="people[3].FirstName" value="Thomas" />
<input type="text" name="people[3].LastName" value="Jefferson" />
Which turns into this as a HTTP POST:
这变成了HTTP POST:
people%5B0%5D.FirstName=George&people%5B0%5D.LastName=Washington&people%5B1%5D.FirstName=Abraham&people%5B1%5D.LastName=Lincoln&people%5B3%5D.FirstName=Thomas&people%5B3%5D.LastName=Jefferson
Which is basically:
基本上是:
people[0].FirstName = "George"
people[0].LastName = "Washington"
people[1].FirstName = "Abraham"
people[1].LastName = "Lincoln"
people[3].FirstName = "Thomas"
people[3].LastName = "Jefferson"
Then it will be just as if we had written this in code:
然后就好像我们已经用代码编写了这个一样:
people = new Person[] {
new Person() { FirstName = "George", LastName = "Washington" },
new Person() { FirstName = "Abraham", LastName = "Lincoln" }
};
The way that we read in the properties is by looking for parameterName[index].PropertyName. The index must be zero-based and unbroken. In the above example, because there was no people[2], we stop after Abraham Lincoln and don’t continue to Thomas Jefferson.
我们在属性中读取的方式是通过查找parameterName [index] .PropertyName 。 索引必须从零开始且不间断。 在上面的示例中,由于没有人[2],我们在亚伯拉罕·林肯之后停下来,不继续去托马斯·杰斐逊。
If the signature looks like this:
如果签名看起来像这样:
public ActionResult Blah(IDictionary<string, Company> stocks) {
// ...
}
And we are given this in HTML:
我们用HTML给出了这个:
<input type="text" name="stocks[0].Key" value="MSFT" />
<input type="text" name="stocks[0].Value.CompanyName" value="Microsoft Corporation" />
<input type="text" name="stocks[0].Value.Industry" value="Computer Software" />
<input type="text" name="stocks[1].Key" value="AAPL" />
<input type="text" name="stocks[1].Value.CompanyName" value="Apple, Inc." />
<input type="text" name="stocks[1].Value.Industry" value="Consumer Devices" />
Which like this:
像这样:
stocks[0].Key = "MSFT"
stocks[0].Value.CompanyName = "Microsoft Corporation"
stocks[0].Value.Industry = "Computer Software"
stocks[1].Key = "AAPL"
stocks[1].Value.CompanyName = "Apple, Inc."
stocks[1].Value.Industry = "Consumer Devices"
Then it will be just as if we had written:
然后就好像我们已经写过:
stocks = new Dictionary<string, Company>() {
{ "MSFT", new Company() { CompanyName = "Microsoft Corporation", Industry = "Computer Software" } },
{ "AAPL", new Company() { CompanyName = "Apple, Inc.", Industry = "Consumer Devices" } }
};
The way that we read in the keys is by looking for parameterName[index].Key, and the way that we read in the values is by looking for parameterName[index].Value. If the key or value type is a complex type (like Company, in the above example), then we treat parameterName[index].Key or parameterName[index].Value as the entire field prefix and start appending the .PropertyName suffix to the end of it. The index must also be zero-based and unbroken, as mentioned previously.
我们在键中读取的方式是通过查找parameterName [index] .Key ,而在值中读取的方式是通过查找parameterName [index] .Value 。 如果键或值类型是复杂类型(例如上例中的Company),则我们将parameterName [index] .Key或parameterName [index] .Value视为整个字段前缀,并开始将.PropertyName后缀附加到结束。 如前所述,索引还必须从零开始且不间断。
Parameters of type IEnumerable<T>, ICollection<T>, IList<T>, T[], Collection<T>, and List<T> are bound using the first syntax. Parameters of type IDictionary<TKey, TValue> and Dictionary<TKey, TValue> are bound using the second syntax.
IEnumerable <T>,ICollection <T>,IList <T>,T [],Collection <T>和List <T>类型的参数使用第一种语法进行绑定。 使用第二种语法绑定IDictionary <TKey,TValue>和Dictionary <TKey,TValue>类型的参数。
Of course, as with most of ASP.NET MVC, if you don't like this behavior you're welcome to change it by writing your own binders for specific types or by pulling the information from a FormCollection directly and doing your own thing.
当然,与大多数ASP.NET MVC一样,如果您不喜欢这种行为,欢迎通过为特定类型编写自己的活页夹或直接从FormCollection中提取信息并做自己的事情来更改它。
Levi adds:
李维补充说:
FWIW – you don’t need the bracket notation if you’re submitting simple types to the server. That is, if your request contains key=foo&key=bar&key=baz, we’ll correctly bind that to an IEnumerable<T>, IList<T>, ICollection<T>, T[], Collection<T>, or List<T>. In the first sentence in this paragraph, "simple type" means a type for which TypeDescriptor.GetConverter(typeof(T)).CanConvertFrom(typeof(string)) returns true. This makes a handful of cases simpler.
FWIW –如果您要向服务器提交简单类型,则不需要括号符号。 也就是说,如果您的请求包含key = foo&key = bar&key = baz ,那么我们会将其正确绑定到IEnumerable <T>,IList <T>,ICollection <T>,T [],Collection <T>或List < T> 。 在本段的第一句话中,“简单类型”表示TypeDescriptor.GetConverter(typeof(T))。CanConvertFrom(typeof(string))返回true的类型。 这使少数情况变得更简单。
Thanks to Levi for the nitty gritty!
感谢Levi的坚韧不拔!
mvvm 绑定字典集合