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

相关文章
相关标签/搜索