本文转载自 ASP.NET MVC数组模型绑定 ,https://www.cnblogs.com/choon/p/5429065.html
内容根据评论内容中的方式有所调整
在ASP.NET MVC中使用Razor语法可以在视图中方便地展示数组,如果要进行数组模型绑定,会遇到索引断裂问题,如下示例:
数组Name在索引3处断裂,在模型绑定器解析完成后,会丢弃后面的4和5,只有0、1、2会被正确解析到对应模型中。
这种断裂在进行动态数组绑定时会经常发生。
下面,以一个案例来探讨如何进行动态数组绑定。假设有以下应用场景:
要求能够动态地添加和删除乘机人,最终提交表单后乘机人信息要填充到视图模型中的一个数组或集合属性中,以方便我们进行后续业务处理。
第一种方式我称之为”占位符替换“,使用的是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);
}
再在视图文件中进行展示:
由于ASP.NET MVC的模型绑定器(DefaultModelBinder)具备自动解析形如"[0].属性名"、"[1].属性名"的能力,所以可以在模板文件中以占位符的形式来表示数组下标:
<!-- 乘机人模板 -->
<script type="text/html" id="passengerTemplate">
<tr>
<td>姓名:</td>
<td><input name="Passengers.Index" type="hidden" value="{}" /><input id="Passengers\_{}\_\_Name" name="Passengers\[{}\].Name" type="text" value=""></td>
<td>身份证号:</td>
<td><input id="Passengers\_{}\_\_IdNo" name="Passengers\[{}\].IdNo" type="text" value=""></td>
<td>
<a href="javascript:;" onclick="removePassenger(this)">删除</a>
</td>
</tr>
</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属性中。
从Request.Form表单里面读取所有不同的索引,拼接索引读取数据。
public class TestModelBinder : DefaultModelBinder, IModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var model = base.BindModel(controllerContext, bindingContext);
var inspectKeys = controllerContext.HttpContext.Request.Form.AllKeys.Where(c => c.Contains("IdNo")).ToList();
List
List
for (int i = ; i < inspectKeys.Count; i++)
{
string result = System.Text.RegularExpressions.Regex.Replace(inspectKeys[i], @"[^0-9]+", "");
if (!inspectLengths.Contains(result) && !string.IsNullOrWhiteSpace(result))
{
inspectLengths.Add(result);
}
}
for (int i = ; i < inspectLengths.Count; i++)
{
Passenger dto = new Passenger()
{
IdNo = controllerContext.HttpContext.Request.Form["IdNo" + inspectLengths[i]],
Name = controllerContext.HttpContext.Request.Form["Name" + inspectLengths[i]],
};
passengerList.Add(dto);
}
var entity = model as OrderModel;
if (entity != null)
{
entity.Passengers = passengerList;
return entity;
}
return model;
}
}
控制器接收代码:
[HttpPost]
public ActionResult Test(Models.OrderModel orderModel)
{
return View(orderModel);
}
文件下载:TestCode.zip
手机扫一扫
移动阅读更方便
你可能感兴趣的文章