本文转载自  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. java上传附件含有%处理或url含有%(URLDecoder: Illegal hex characters in escape (%) pattern - For input string)

    在附件名称中含有%的时候,上传附件进行url编码解析的时候会出错,抛出异常: Exception in thread "main" java.lang.IllegalArgumen ...

  2. PLSQL连接oracle12c

    一.本人以前都是使用oracle10g客户端,PLSQL连接oracle12c时报错 确认配置完全没问题,纠结了不少时间.后来查的是oracle客户端太老了,版本11.2.0.2.0以上即可 二.下载 ...

  3. Session过期,如何跳出iframe框架页的问题

    跳出框架页,实际上是更改父页面地址.那么更改父页面地址很简单即: window.parent.location='/Login/loginindex'; 这里说session过期,那么浏览器端的任何请 ...

  4. boost algorithm

    BOost Algorithm provides algorithms that complement the algorithms from the standard library. Unlike ...

  5. Mybatis原理及源码分析

    什么是Mybatis? Mybatis是一个半自动化的持久层框架. Mybatis可以将向PreparedStatement中的输入参数自动进行映射(输入映射),将结果集映射成Java对象(输出映射) ...

  6. 【LeetCode 75】颜色分类

    题目链接 [题解] 维护一个左边界l和一个右边界r 其中0..l-1都是'0' 而 r+1..n-1都是'2' 我们令i=l;i<=r; 枚举每一个a[i]; ①如果a[i]=2.那么把a[i] ...

  7. Windows Server服务器之Linux server与windows server的区别

    Linux server与windows server的区别用linux做server,相对于windows server有什么优势? 首先,平均故障时间少,只要配置和使用得当,linux的平均故障( ...

  8. BUUCTF | easy_tornado

    第一次遇到模板注入的题,赶紧记笔记,此篇相当于对大佬的做法的复现Orz,师傅太强了https://blog.csdn.net/weixin_44255856/article/details/97687 ...

  9. servlet3.0 异步处理

    转:https://blog.csdn.net/benjamin_whx/article/details/38874657 13.1.概述 计算机的内存是有限的.Servlet/JSP容器的设计者很清 ...

  10. linux设备驱动第一篇:设备驱动程序简介

    首先,我们知道驱动是内核的一部分,那么驱动在内核中到底扮演了什么角色呢? 设备驱动程序在内核中的角色:他们是一个个独立的“黑盒子”,使某个特定的硬件响应一个定义良好的内部编程接口,这些接口完全隐藏了设 ...