Razor 保存动态表格
阅读原文时间:2023年07月16日阅读:1

本文转载自  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);

}

再在视图文件中进行展示:


@Html.TextBoxFor(p => p.FlightNo, new { placeholder = "航班号" })
@if (Model.Passengers != null && Model.Passengers.Count > 0) { for (int i = 0; i < Model.Passengers.Count; i++) { } }
姓名: @Html.TextBoxFor(p => Model.Passengers\[i\].Name) 身份证号: @Html.TextBoxFor(p => Model.Passengers\[i\].IdNo) 删除
@\*\*@

由于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 passengerList = new List();
List inspectLengths = new 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

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章