Http Request 到Input Model的绑定按照model的类型可分为四种情况。
- Primitive type
- Collection of primitive type
- Complex type
- Collection of complex type
首先理解Value Privider and Precedence
Model Binder是利用Value Provider来获取相关数据的。
1. Primitive type
Controller Method:
public class BindingController : Controller { public ActionResult Repeat(String text, Int32 number) { var model = new RepeatViewModel {Number = number, Text = text}; return View(model); } }
Http Request : 采用Query String 方式
http://server/binding/repeat?text=Dino&number=2
2. Complex type
Complex Type:
public class RepeatText { public String Text { get; set; } public Int32 Number { get; set; } }
Controller Method:
public class ComplexController : Controller { public ActionResult Repeat(RepeatText inputModel) { var model = new RepeatViewModel { Title = "Repeating text", Text = inputModel.Text, Number = inputModel.Number }; return View(model); } }
Http Request : 采用Query String 方式
http://server/binding/repeat?text=Dino&number=2
Model Binder 将从posted data中寻找Key name与Property Name匹配的。从而可以实例化RepeatText对象。
3. Collection of primitive type
Form :
@using (Html.BeginForm()) { <h2>List your email address(es)</h2> foreach(var email in Model.Emails) { <input type="text" name="emails" value="@email" /> <br /> } <input type="submit" value="Send" /> }
Controller Method:
public ActionResult Emails(IList<String> emails) { ... }
In the end, to ensure that a collection of values is passed to a controller method, you need to
ensure that elements with the same ID are emitted to the response stream.
4. Collection of complex type
Complex Type:
public class Country { public Country() { Details = new CountryInfo(); } public String Name { get; set; } public CountryInfo Details { get; set; } } public class CountryInfo { public String Capital { get; set; } public String Continent { get; set; } }
Controller Method:
[ActionName("Countries")] [HttpPost] public ActionResult ListCountriesForPost(IList<Country> countries) { ... }
Form:
@using (Html.BeginForm()) { <h2>Select your favorite countries</h2> var index = 0; foreach (var country in Model.CountryList) { <fieldset> <div> <b>Name</b><br /> <input type="text" name="countries[@index].Name" value="@country.Name" /><br /> <b>Capital</b><br /> <input type="text" name="countries[@index].Details.Capital" value="@country.Details.Capital" /><br /> <b>Continent</b><br /> @{ var id = String.Format("countries[{0}].Details.Continent", index++); } @Html.TextBox(id, country.Details.Continent) <br /> </div> </fieldset> } <input type="submit" value="Send" /> }
总结:
如果default model binder不能适应需求则需要开发custom model binder。例如用三个TextBox实现一个DateHelper。