Razor 保存動態表格

本文轉載自  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 addPassenger() {
            var index =new GUID(); ///-----------------隨便生成一個 Index Key
            var passengerHTML = $('#passengerTemplate').html().replace(/{}/g, index);
            $(".passenger").find("tbody").append($(passengerHTML));
        }

當刪除伺機人時,由於存在隱藏域,不須要考慮索引斷裂問題

// 刪除伺機人
function  removePassenger(e) {
      $(e).parents("tr").remove();
}

這樣,當咱們提交表單時,伺機人信息就會自動填充到模型的Passengers屬性中。

方式二:重寫DefaultModelBinder

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

相關文章
相關標籤/搜索