本文转载自 ASP.NET MVC数组模型绑定 ,https://www.cnblogs.com/choon/p/5429065.htmljavascript
内容根据评论内容中的方式有所调整html
在ASP.NET MVC中使用Razor语法能够在视图中方便地展现数组,若是要进行数组模型绑定,会遇到索引断裂问题,以下示例:前端
<input type="text" name="[0].Name" />java
<input type="text" name="[1].Name" />数组
<input type="text" name="[2].Name" />app
<input type="text" name="[4].Name" />ide
<input type="text" name="[5].Name" />post
数组Name在索引3处断裂,在模型绑定器解析完成后,会丢弃后面的4和5,只有0、一、2会被正确解析到对应模型中。this
这种断裂在进行动态数组绑定时会常常发生。spa
下面,以一个案例来探讨如何进行动态数组绑定。假设有如下应用场景:
要求可以动态地添加和删除伺机人,最终提交表单后伺机人信息要填充到视图模型中的一个数组或集合属性中,以方便咱们进行后续业务处理。
第一种方式我称之为”占位符替换“,使用的是ASP.NET MVC默认的模型绑定器(DefaultModelBinder)并结合前端处理。
首先,第一步,根据业务场景设计视图模型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public
class
OrderModel
{
/// <summary>
/// 航班号
/// </summary>
public
string
FlightNo {
get
;
set
; }
/// <summary>
/// 伺机人
/// </summary>
public
List<Passenger> Passengers {
get
;
set
; }
}
public
class
Passenger
{
public
string
Name {
get
;
set
; }
public
string
IdNo {
get
;
set
; }
}
|
其次,将此视图模型传递给视图:
1
2
3
4
5
6
7
8
|
public
ActionResult New()
{
Models.OrderModel orderModel =
new
Models.OrderModel();
List<Models.Passenger> passenger =
new
List<Models.Passenger>();
passenger.Add(
new
Models.Passenger());
orderModel.Passengers = passenger;
return
View(orderModel);
}
|
再在视图文件中进行展现:
1 <div style="width:680px"> 2 <form method="post" id="postForm"> 3 <div class="form-group"> 4 <label>航班</label><br /> 5 @Html.TextBoxFor(p => p.FlightNo, new { placeholder = "航班号" }) 6 </div> 7 <div class="form-group"> 8 <label>伺机人</label> 9 <table class="passenger"> 10 <tbody> 11 @if (Model.Passengers != null && Model.Passengers.Count > 0) 12 { 13 for (int i = 0; i < Model.Passengers.Count; i++) 14 { 15 <tr> 16 <td>姓名:</td> 17 <td>@Html.TextBoxFor(p => Model.Passengers[i].Name) <input name="Passengers.Index" type="hidden" value="@i" /></td> 18 <td>身份证号:</td> 19 <td>@Html.TextBoxFor(p => Model.Passengers[i].IdNo)</td> 20 <td> 21 <a href="javascript:;" onclick="removePassenger(this)">删除</a> 22 </td> 23 </tr> 24 } 25 } 26 </tbody> 27 </table> 28 <div style="margin-top:10px"> 29 <a href="javascript:;" onclick="addPassenger()">添加伺机人</a> 30 </div> 31 </div> 32 @*<button type="submit">提交</button>*@ 33 <button type="button" onclick="myfunction()">提交</button> 34 </form> 35 </div>
因为ASP.NET MVC的模型绑定器(DefaultModelBinder)具有自动解析形如"[0].属性名"、"[1].属性名"的能力,因此能够在模板文件中以占位符的形式来表示数组下标:
1 <!-- 伺机人模板 --> 2 <script type="text/html" id="passengerTemplate"> 3 <tr> 4 <td>姓名:</td> 5 <td><input name="Passengers.Index" type="hidden" value="{}" /><input id="Passengers_{}__Name" name="Passengers[{}].Name" type="text" value=""></td> 6 <td>身份证号:</td> 7 <td><input id="Passengers_{}__IdNo" name="Passengers[{}].IdNo" type="text" value=""></td> 8 <td> 9 <a href="javascript:;" onclick="removePassenger(this)">删除</a> 10 </td> 11 </tr> 12 </script>
以上代码中的"{}"是数组下标占位符。当添加伺机人时,可预先随机生成一个key,而后再使用JavaScript替换”{}“为数组下标。
// 添加伺机人
当删除伺机人时,由于存在隐藏域,不须要考虑索引断裂问题:
// 删除伺机人
function
removePassenger(e) {
$(e).parents("tr").remove();
}
这样,当咱们提交表单时,伺机人信息就会自动填充到模型的Passengers属性中。
从Request.Form表单里面读取全部不一样的索引,拼接索引读取数据。
1 public class TestModelBinder : DefaultModelBinder, IModelBinder 2 { 3 public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 4 { 5 var model = base.BindModel(controllerContext, bindingContext); 6 var inspectKeys = controllerContext.HttpContext.Request.Form.AllKeys.Where(c => c.Contains("IdNo")).ToList(); 7 List<Passenger> passengerList = new List<Passenger>(); 8 List<string> inspectLengths = new List<string>(); 9 for (int i = 0; i < inspectKeys.Count; i++) 10 { 11 string result = System.Text.RegularExpressions.Regex.Replace(inspectKeys[i], @"[^0-9]+", ""); 12 if (!inspectLengths.Contains(result) && !string.IsNullOrWhiteSpace(result)) 13 { 14 inspectLengths.Add(result); 15 } 16 } 17 for (int i = 0; i < inspectLengths.Count; i++) 18 { 19 Passenger dto = new Passenger() 20 { 21 IdNo = controllerContext.HttpContext.Request.Form["IdNo" + inspectLengths[i]], 22 Name = controllerContext.HttpContext.Request.Form["Name" + inspectLengths[i]], 23 }; 24 passengerList.Add(dto); 25 } 26 var entity = model as OrderModel; 27 if (entity != null) 28 { 29 entity.Passengers = passengerList; 30 return entity; 31 } 32 return model; 33 } 34 }
控制器接收代码:
1 [HttpPost] 2 public ActionResult Test(Models.OrderModel orderModel) 3 { 4 return View(orderModel); 5 }
文件下载:TestCode.zip