本文轉載自 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