在MVC控制器里面使用dynamic和ExpandoObject,实现数据转义的输出
在很多时候,我们在数据库里面定义表字段和实际在页面中展示的内容,往往是不太匹配的,页面数据可能是多个表数据的综合体,因此除了我们在表设计的时候考虑周到外,还需要考虑数据展现的处理。如果是常规的处理,那么需要对部分外键字段进行特别的转义处理,如果需要增加多一些字段,那么这种处理可能就相对比较麻烦一些。本文介绍如何在MVC控制器里面使用dynamic和ExpandoObject,实现数据转义后一体化的输出,包括增加任意多的字段信息。
1、数据信息的展示
一般情况下,我们在界面里面展示的信息是相对比较丰富的,尽管我们设计数据表的时候,考虑的是如何精简且避免重复,但是在界面上展示的信息,往往是考虑如何让用户更加方便,因此可能尽可能的展示相关信息。
如对于这样的场景,设备信息作为主要的基础信息,其相关的业务包括设备检查、设备维护、设备报修等信息,如下所示。

基于上面的数据设计,我们如果在展示设备检查、设备维护、设备报修等信息的时候,那么我们一般还需要展示部分的设备基础信息,这样我们更容易了解整个记录数据,但是我们在数据设计的时候,是把它们分开的,因此需要在输出到界面的时候,把它们综合起来。
我以前在《基于MVC4+EasyUI的Web开发框架经验总结(9)--在Datagrid里面实现外键字段的转义操作》介绍过一些数据转义的处理,不过那种方式并不是比较理想的方式。本篇介绍的使用dynamic和ExpandoObject才是我理想的处理模式。
我们来看看我最终通过这种方式实现的界面效果,之后我们再来一步步介绍如何实现这个操作过程的。

2、数据转义的实现
在上面的界面效果里面,我们是基于MVC实现后台的处理,在界面上利用Bootstrap进行展示的(利用EaysUI组件也是类似的处理)。我们分为两部分进行介绍实现的,一部分是采用MVC的输出数据,一部分是界面的展示。
1)MVC的控制器数据处理
在MVC里面,我们一般通过基类的FindWithPager进行数据的分页处理,基于如何在MVC控制器里面实现数据的分页处理,大家感兴趣可以参考《基于Metronic的Bootstrap开发框架经验总结(2)--列表分页处理和插件JSTree的使用》随笔进行了解。
常规的做法,如果是主表信息,我们可以把它们简单的输出,如下所示。
public override ActionResult FindWithPager()
{
//检查用户是否有权限,否则抛出MyDenyAccessException异常
base.CheckAuthorized(AuthorizeKey.ListKey); string where = GetPagerCondition();
PagerInfo pagerInfo = GetPagerInfo();
List<DeviceInfo> list = baseBLL.FindWithPager(where, pagerInfo); //Json格式的要求{total:22,rows:{}}
//构造成Json的格式传递
var result = new { total = pagerInfo.RecordCount, rows = list };
return ToJsonContentDate(result);
}
也就是不需要经过任何转义就直接把查询到的数据列表输出给调用者,由界面进行数据的筛选处理。
如果对于上面提到的设备检查、设备维修等和设备信息相关的,我们就需要利用dynamic和ExpandoObject,把设备信息整合一起提供给界面了,具体代码如下所示。
我们首先对查询的记录进行遍历,把每条记录进行转换,如下所示。
List<ExpandoObject> objList = new List<ExpandoObject>();
foreach (DeviceCheckInfo info in list)
{
dynamic obj = new ExpandoObject();
注意上面我们定义了List<ExpandoObject>的列表和dynamic obj的对象,这样我们通过动态定义的对象,把我们需要的字段属性加到动态对象里面,然后放到集合里面即可。
完整的分页控制器代码如下所示。
public override ActionResult FindWithPager()
{
//检查用户是否有权限,否则抛出MyDenyAccessException异常
base.CheckAuthorized(AuthorizeKey.ListKey); string where = GetPagerCondition();
PagerInfo pagerInfo = GetPagerInfo();
List<DeviceCheckInfo> list = baseBLL.FindWithPager(where, pagerInfo); //设备编码 所属科室 品牌 品类 型号 设备序列号 检查时间 处理人
List<ExpandoObject> objList = new List<ExpandoObject>();
foreach (DeviceCheckInfo info in list)
{
dynamic obj = new ExpandoObject(); DeviceInfo deviceInfo = BLLFactory<Device>.Instance.FindByCode(info.DeviceCode);
if (deviceInfo != null)
{
obj.Dept = deviceInfo.Dept;
obj.Brand = deviceInfo.Brand;
obj.Name = deviceInfo.Name;
obj.Model = deviceInfo.Model;
obj.SerialNo = deviceInfo.SerialNo;
}
obj.ID = info.ID;
obj.DeviceCode = info.DeviceCode;
obj.OperateTime = info.OperateTime;
obj.Operator = info.Operator; objList.Add(obj);
} //Json格式的要求{total:22,rows:{}}
//构造成Json的格式传递
var result = new { total = pagerInfo.RecordCount, rows = objList };
return ToJsonContentDate(result);
}
2)界面的数据展示
上面定义了数据的获取方式,也就是我们需要任何数据都可以在MVC控制器里面,通过动态属性的方式添加到集合对象里面,从而简化了我们界面的处理,我们只需要把获得的信息展示在界面上即可,非常简便了。
界面视图的HTML代码如下所示
<table id="grid" class="table table-striped table-bordered table-hover" cellpadding="0" cellspacing="0" border="0" class="display" width="100%">
<thead id="grid_head">
<tr>
<!--设备编码 所属科室 品牌 品类 型号 设备序列号 检查时间 处理人 -->
<th class="table-checkbox" style="width:40px"><input class="group-checkable" type="checkbox" onclick="selectAll(this)"></th>
<th>设备编码</th>
<th>所属科室</th>
<th>品牌</th>
<th>品类</th>
<th>型号</th>
<th>设备序列号</th>
<th>检查时间</th>
<th>处理人</th>
<th style="width:90px">操作</th>
</tr>
</thead>
<tbody id="grid_body"></tbody>
</table>
我们绑定到界面上,是通过Ajax的方式获取数据,然后绑定显示的,JS代码如下所示。
function SearchCondition(page, condition) {
//获取Json对象集合,并生成数据显示内容
url = "/DeviceCheck/FindWithPager?page=" + page + "&rows=" + rows;
$.getJSON(url + "&" + condition, function (data) {
$("#totalCount").text(data.total);
$("#totalPageCount").text(Math.ceil(data.total / rows));
$("#grid_body").html("");
//<!--设备编码 所属科室 品牌 品类 型号 设备序列号 检查时间 处理人 -->
$.each(data.rows, function (i, item) {
var tr = "<tr>";
tr += "<td><input class='checkboxes' type=\"checkbox\" name=\"checkbox\" value=" + item.ID + "></td>";
tr += "<td>" + item.DeviceCode + "</td>";
tr += "<td>" + item.Dept + "</td>";
tr += "<td>" + item.Brand + "</td>";
tr += "<td>" + item.Name + "</td>";
tr += "<td>" + item.Model + "</td>";
tr += "<td>" + item.SerialNo + "</td>";
tr += "<td>" + item.OperateTime + "</td>";
tr += "<td>" + item.Operator + "</td>";
tr += getActionHtml(item.ID); //获取查看、编辑、删除操作代码
tr += "</tr>";
$("#grid_body").append(tr);
});
//设置分页属性及处理
var element = $('#grid_paging');
if(data.total > 0) {
var options = {
bootstrapMajorVersion: 3,
currentPage: page,
numberOfPages: rows,
totalPages: Math.ceil(data.total / rows),
onPageChanged: function (event, oldPage, newPage) {
SearchCondition(newPage, condition); //页面变化时触发内容更新
}
}
element.bootstrapPaginator(options);
} else {
element.html("");
}
});
}
这样就最终优雅的实现了我们前面介绍的界面效果了。

在MVC控制器里面使用dynamic和ExpandoObject,实现数据转义的输出的更多相关文章
- MVC控制器里面使用dynamic和ExpandoObject
MVC控制器里面使用dynamic和ExpandoObject 在很多时候,我们在数据库里面定义表字段和实际在页面中展示的内容,往往是不太匹配的,页面数据可能是多个表数据的综合体,因此除了我们在表设计 ...
- 在ASP.NET MVC控制器中获取链接中的路由数据
在ASP.NET MVC中,在链接中附加路由数据有2种方式.一种是把路由数据放在匿名对象中传递: <a href="@Url.Action("GetRouteData&quo ...
- MVC 控制器中传递dynamic(对象) 给视图
有时候不想重新定义一个实体,则使用 dynamic 来定义匿名类型. //匿名类型 传递到前台 Model dynamic viewModel = new { UserID = 5016 }; ret ...
- MVC控制器传递多个实体类集合到视图的方案总结
MVC控制器向视图传递数据包含多个实体类的解决方案有很多,这里主要针对视图模型.动态模型以及Tuple三种方法进行一些总结与记录. 基础集合类:TableA namespace ViewModelSt ...
- 详解ASP.NET MVC 控制器
1 概述 在阅读本篇博文时,建议结合上篇博文:详解ASP.NET MVC 路由 一起阅读,效果可能会更好些. Controller(控制器)在ASP.NET MVC中负责控制所有客户端与服务端的 ...
- 【ASP.NET MVC系列】浅谈ASP.NET MVC 控制器
ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...
- ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则
ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...
- ABP文档 - Mvc 控制器
文档目录 本节内容: 简介 AbpController基类 本地化 其它 过滤 异常处理和结果包装 审计日志 验证 授权 工作单元 反伪造 模型绑定器 简介 ABP通过nuget包Abp.Web.Mv ...
- ABP理论学习之MVC控制器(新增)
返回总目录 本篇目录 介绍 AbpController基类 本地化 异常处理 响应结果的包装 审计日志 授权 工作单元 其他 介绍 ABP通过Abp.Web.Mvc nuget包集成了ASP.NET ...
随机推荐
- 思维导图FreeMind
什么是MindMap? MindMap(被译成思维导图或心智图)是一种思维工具,由英国的记忆之父托尼-博赞发明. MindMap是一种新的思维模式,它将左脑的逻辑.顺序.条例.文字.数字,以及右脑的图 ...
- 阿里聚安全受邀参加SFDC安全大会,分享互联网业务面临问题和安全创新实践
现今,技术引领的商业变革已无缝渗透入我们的日常生活,「技术改变生活」的开发者们被推向了创新浪潮的顶端.国内知名的开发者技术社区 SegmentFault 至今已有四年多了,自技术问答开始,他们已经发展 ...
- 辛巴学院-Unity-剑英陪你零基础学c#系列(三)计算与类型
辛巴学院:正大光明的不务正业. 中秋节快乐,每逢佳节倍思亲,尤其是那素未谋面的老婆,对吧,屌丝们. 今天我们来探索一下C#里面奇怪的计算,奇怪的类型. 奇怪的计算 当我刚刚接触计算机编程的时候,一 ...
- Java static 的一两点使用
这篇文章是关于Java static关键字的使用,主要会介绍以下的内容: static 的概念 static的各种应用 总结 static 是什么 static 顾名思义是静态的意思.与this相对, ...
- [大数据之Sqoop] —— 什么是Sqoop?
介绍 sqoop是一款用于hadoop和关系型数据库之间数据导入导出的工具.你可以通过sqoop把数据从数据库(比如mysql,oracle)导入到hdfs中:也可以把数据从hdfs中导出到关系型数据 ...
- Android开发学习之路-带文字的图片分享
有用过微信分享SDK的都应该知道,微信分享到朋友圈的时候是不能同时分享图片和文字的,只要有缩略图,那么文字就不会生效.那么问题就来了,如果我们想把APP内的某些内容连带图片一起分享到微信,是不是没办法 ...
- WCF 安全性 之 Windows
案例下载 http://download.csdn.net/detail/woxpp/4113172 服务端配置代码 <system.serviceModel> <services& ...
- JS面向对象(3) -- Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对 ...
- 日志log2
public class LoggerHelper2 { private static ConcurrentQueue<string> CqMsg = null; private stat ...
- IM消息送达保证机制实现(二):保证离线消息的可靠投递
1.前言 本文的上篇<IM消息送达保证机制实现(一):保证在线实时消息的可靠投递>中,我们讨论了在线实时消息的投递可以通过应用层的确认.发送方的超时重传.接收方的去重等手段来保证业务层面消 ...