本文转载自  ASP.NET MVC数组模型绑定 ,https://www.cnblogs.com/choon/p/5429065.html

内容根据评论内容中的方式有所调整

在ASP.NET MVC中使用Razor语法可以在视图中方便地展示数组,如果要进行数组模型绑定,会遇到索引断裂问题,如下示例:

<input type="text" name="[0].Name" />

<input type="text" name="[1].Name" />

<input type="text" name="[2].Name" />

<input type="text" name="[4].Name" />

<input type="text" name="[5].Name" />

数组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 { getset; }
    /// <summary>
    /// 乘机人
    /// </summary>
    public List<Passenger> Passengers { getset; }
}
 
public class Passenger
{
    public string Name { getset; }
    public string IdNo { getset; }
}

其次,将此视图模型传递给视图:

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);
}

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

 <div style="width:680px">
<form method="post" id="postForm">
<div class="form-group">
<label>航班</label><br />
@Html.TextBoxFor(p => p.FlightNo, new { placeholder = "航班号" })
</div>
<div class="form-group">
<label>乘机人</label>
<table class="passenger">
<tbody>
@if (Model.Passengers != null && Model.Passengers.Count > 0)
{
for (int i = 0; i < Model.Passengers.Count; i++)
{
<tr>
<td>姓名:</td>
<td>@Html.TextBoxFor(p => Model.Passengers[i].Name) <input name="Passengers.Index" type="hidden" value="@i" /></td>
<td>身份证号:</td>
<td>@Html.TextBoxFor(p => Model.Passengers[i].IdNo)</td>
<td>
<a href="javascript:;" onclick="removePassenger(this)">删除</a>
</td>
</tr>
}
}
</tbody>
</table>
<div style="margin-top:10px">
<a href="javascript:;" onclick="addPassenger()">添加乘机人</a>
</div>
</div>
@*<button type="submit">提交</button>*@
<button type="button" onclick="myfunction()">提交</button>
</form>
</div>

由于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属性中。

方式二:重写DefaultModelBinder

从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<Passenger> passengerList = new List<Passenger>();
List<string> inspectLengths = new List<string>();
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

Razor 保存动态表格的更多相关文章

  1. Java利用poi生成word(包含插入图片,动态表格,行合并)

    转(小改): Java利用poi生成word(包含插入图片,动态表格,行合并) 2018年12月20日 09:06:51 wjw_11093010 阅读数:70 Java利用poi生成word(包含插 ...

  2. 基于.NetCore开发博客项目 StarBlog - (12) Razor页面动态编译

    系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...

  3. 【设计过程】.NET ORM FreeSql WhereDynamicFilter 动态表格查询功能

    前言 最近几乎每天40度,越热越不想面对电脑,还好开源项目都比较稳定没那么多待解决问题,趁着暑假带着女儿学习游泳已略有小成.游泳好处太多了,建议有孩子的都去学学,我是在岸边指导大约一周左右就学会了,目 ...

  4. 在<s:iterator>标签里给动态表格添加序号

    在<s:iterator>标签里给动态表格添加序号,需要用到<s:iterator>标签里的Status属性里的count eg:<s:iterator value=&q ...

  5. HTML5&CSS3经典动态表格

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 5.11-5.15javascript制作动态表格

    制作动态表格的主要是运用js中表格类的insertRow.insertCell简易添加行和列的代码,不过要注意每行添加的表格是有位置行编号的,每行的编号为rows.length-1,增加的表格内的标签 ...

  7. winfrom之动态控件生成以及保存动态空间的数据

    前些天要完成一个winform程序,里面涉及到动态控件的添加以及保存动态空间中数据的保存,效果如下 初始化时: 点击添加阶梯价后:(点击一下,动态添加一行) 那么接下来,我们就具体的讲下代码实现: 首 ...

  8. Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成)

    Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成) 动态表单生成 ElementUI官网引导 Element表单生成 Element动态增减表单,在线代码 关键配置 templa ...

  9. jQuery的下面是动态表格动态表单中的HTML代码

    动态表格动态表单中的Jquery代码 <script type="text/javascript" src="/include/jquery/jquery-1.1. ...

随机推荐

  1. [转载]解决Android studio新建项目慢的问题

    原文地址为:https://blog.csdn.net/easion_zms/article/details/73181402 Android Studio 好处很多,但是当从github上或者导入其 ...

  2. 【串线篇】sql注入问题

    一.什么是SQL注入?? 二.mybatis是如何避免这种情况的呐? 这就得益于mybatis在底层实现时使用预编译语句.数据库在执行该语句时,直接使用预编译的语句,然后用传入的userId替换占位符 ...

  3. 异常 Cannot resolve class or package

    spring boot yml配置异常Cannot resolve class or package 是因为mvaen设置 pom.xml的文件配置如上,scope 范围指定为runtime,runt ...

  4. $NOI2014$ 购票(斜率优化 点分治)

    \(NOI2014\)购票 哇终于可以碰电脑了赶快切些火题找找感觉. 拿到这道题的时候发现简单的斜率优化推一推可以秒掉平方做法,然后一条链也可以做. 然后呢... 卧槽这个在一棵树上怎么办啊. 大力\ ...

  5. pycharm远程连接的步骤(有一项需特别注意)

    1.设置远程服务器,在这里配置服务器地址等: 要注意下边的这个mappings设置好,跟编译器的path mapping设置为同一个,这里我没设置为同一个,后边就出现了点问题. 2.配置远程的编译器 ...

  6. 2019 牛客暑期多校 第三场 F Planting Trees (单调队列+尺取)

    题目:https://ac.nowcoder.com/acm/contest/883/F 题意:求一个矩阵最大面积,这个矩阵的要求是矩阵内最小值与最大值差值<=m 思路:首先我们仔细观察范围,我 ...

  7. [HDU3117]Fibonacci Numbers

    题目:Fibonacci Numbers 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3117 分析: 1)后四位可以用矩阵快速幂解决.$T= \left ...

  8. Linux二进制程序安装使用

    下载好的二进制,压缩包解压,或者直接是二进制. 放到想要的目录 在 /etc/environment 双引号前面添加程序路径 以:开头,\结尾可以换行 接下来修改sudo ,不然sudo会找不到 以下 ...

  9. 【Jmeter基础】 Linux上运行Jmeter

    Jmeter 是一个强大的并发压测工具,常用于性能测试,压力测试,接口测试等领域.本文将介绍如下内容: 1. Jmeter 执行阶梯式压测 2. Jmeter 如何压测网站的js,css 等资源 3. ...

  10. python导入自定义模块和包

    参考资料 https://blog.csdn.net/gvfdbdf/article/details/52084144 http://www.runoob.com/python/python-modu ...