在很多时候,我们在数据库里面定义表字段和实际在页面中展示的内容,往往是不太匹配的,页面数据可能是多个表数据的综合体,因此除了我们在表设计的时候考虑周到外,还需要考虑数据展现的处理。如果是常规的处理,那么需要对部分外键字段进行特别的转义处理,如果需要增加多一些字段,那么这种处理可能就相对比较麻烦一些。本文介绍如何在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,实现数据转义的输出的更多相关文章

  1. MVC控制器里面使用dynamic和ExpandoObject

    MVC控制器里面使用dynamic和ExpandoObject 在很多时候,我们在数据库里面定义表字段和实际在页面中展示的内容,往往是不太匹配的,页面数据可能是多个表数据的综合体,因此除了我们在表设计 ...

  2. 在ASP.NET MVC控制器中获取链接中的路由数据

    在ASP.NET MVC中,在链接中附加路由数据有2种方式.一种是把路由数据放在匿名对象中传递: <a href="@Url.Action("GetRouteData&quo ...

  3. MVC 控制器中传递dynamic(对象) 给视图

    有时候不想重新定义一个实体,则使用 dynamic 来定义匿名类型. //匿名类型 传递到前台 Model dynamic viewModel = new { UserID = 5016 }; ret ...

  4. MVC控制器传递多个实体类集合到视图的方案总结

    MVC控制器向视图传递数据包含多个实体类的解决方案有很多,这里主要针对视图模型.动态模型以及Tuple三种方法进行一些总结与记录. 基础集合类:TableA namespace ViewModelSt ...

  5. 详解ASP.NET MVC 控制器

    1   概述 在阅读本篇博文时,建议结合上篇博文:详解ASP.NET MVC 路由  一起阅读,效果可能会更好些. Controller(控制器)在ASP.NET MVC中负责控制所有客户端与服务端的 ...

  6. 【ASP.NET MVC系列】浅谈ASP.NET MVC 控制器

    ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...

  7. 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 ...

  8. ABP文档 - Mvc 控制器

    文档目录 本节内容: 简介 AbpController基类 本地化 其它 过滤 异常处理和结果包装 审计日志 验证 授权 工作单元 反伪造 模型绑定器 简介 ABP通过nuget包Abp.Web.Mv ...

  9. ABP理论学习之MVC控制器(新增)

    返回总目录 本篇目录 介绍 AbpController基类 本地化 异常处理 响应结果的包装 审计日志 授权 工作单元 其他 介绍 ABP通过Abp.Web.Mvc nuget包集成了ASP.NET ...

随机推荐

  1. SQL Server全时区转换

    SQL Server全时区转换 假如你的应用程序是跨国(例如跨国银行交易)使用的话,那么数据库的一些国际化特性支持可以说是非常重要 其中最常见的就是各国时区上的差异,由于SQL Server getd ...

  2. 使用EntityFramework6连接MySql数据库(db first方式)

    准备工具: VS2013.MySQL For VisualStudio 1.1.4.Connector/Net 6.8.3(百度网盘里) 程序包管理器执行命令: Install-Package Ent ...

  3. SQLite vs MySQL vs PostgreSQL:关系型数据库比较

    自1970年埃德加·科德提出关系模型之后,关系型数据库便开始出现,经过了40多年的演化,如今的关系型数据库种类繁多,功能强大,使用广泛.面对如此之多的关系型数据库,我们应该如何权衡找出适合自己应用场景 ...

  4. 简单一招实现json数据可视化

    开发一个内部功能时碰到的需求,要把json数据在页面上展示出来,平时浏览器会安装jsonView这样的扩展来看json数据,但是程序要用到的话该怎么办呢?今天在网上搜索的时候,发现了这个小技巧,分享一 ...

  5. 【单元测试】NUint使用详解及Visual Studio配置

    阅读目录 什么是单元测试? 为什么使用单元测试? NUint使用详解: 示例 属性 断言 简单测试 VS配置: External Tools Visual Nunit 2010 NUnit Test ...

  6. [转]GC简介

    [转]GC简介 原文链接:http://www.cnblogs.com/cposture/p/4845189.html 原文写得太好了,这里转一下. 1 GC机制 1.1 对象 从计算机的角度,装有数 ...

  7. 移动APP服务端设计开发注意要点

    2014年,移动APP的热度丝毫没有减退,怎么为您的移动端app设计良好的服务器端接口(API)呢? 下面谈谈我个人的一些想法. 2014年,移动APP的热度丝毫没有减退,并没有像桌面软件被WEB网站 ...

  8. kindeditor 去掉网络图片上传功能

    kindeditor是一款开源的富文本编辑器,其内容设置均为可配置,使用比较灵活. 去掉网络图片的页面:allowImageRemote: false, 修改上传的图片的name:filePostNa ...

  9. Win8换成Win7系统问题小结(修改主板BIOS方法)

    问题描述: 笔记本电脑W8系统使用不习惯,想要换成W7系统,但不管是用光盘安装亦或是用U盘安装,在设置系统启动项的时候,选择从光盘启动或从U盘启动,但是回车点了之后没反应. 下面就说说问题的原因及解决 ...

  10. 在drawable 画胶囊状

    <solid android:color="@color/colorAccent"></solid> <corners android:radius= ...