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的更多相关文章

  1. 在MVC控制器里面使用dynamic和ExpandoObject,实现数据转义的输出

    在很多时候,我们在数据库里面定义表字段和实际在页面中展示的内容,往往是不太匹配的,页面数据可能是多个表数据的综合体,因此除了我们在表设计的时候考虑周到外,还需要考虑数据展现的处理.如果是常规的处理,那 ...

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

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

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

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

  4. 详解ASP.NET MVC 控制器

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

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

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

  6. ABP文档 - Mvc 控制器

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

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

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

  8. ASP.NET MVC 控制器激活(一)

    ASP.NET MVC 控制器激活(一) 前言 在路由的篇章中讲解了路由的作用,讲着讲着就到了控制器部分了,从本篇开始来讲解MVC中的控制器,控制器是怎么来的?MVC框架对它做了什么?以及前面有的篇幅 ...

  9. ASP.NET MVC 控制器激活(二)

    ASP.NET MVC 控制器激活(二) 前言 在之前的篇幅中,用文字和图像来表示了控制器的激活过程,描述的角度都是从框架默认实现的角度去进行描述的,这样也使得大家都可以清楚的知道激活的过程以及其中涉 ...

随机推荐

  1. android蓝牙(二)——接收数据

    在蓝牙开发中,我们有这种一个需求:我们的androidclient要始终保持和蓝牙的连接,当蓝牙有数据返回的时候,androidclient就要及时的收取数据,当蓝牙没有数据返回的时候我们就要保持an ...

  2. jQuery 之 $(this) 出了什么问题?

    近期在写jQuery的时候出了这样一个问题? <html> <head> <title></title> </head> <style ...

  3. iOS 之使用CAShapeLayer中的CAGradientLayer实现圆环的颜色渐变

    本文转载自:http://blog.csdn.net/zhoutao198712/article/details/20864143 在 Github上看到一些进度条的功能,都是通过Core Graph ...

  4. Jquery UI accordion手风琴菜单

    最近学习jQuery,总结了一些心得. 1.引用 <script type="text/javascript" src=jquery.js></script> ...

  5. tomcat编译通过问题

    tomcat  编译后 的类 和 网站目录不能同名!

  6. 在线QQ客服

    代码一: <a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=451314789&si ...

  7. 正态分布(Normal distribution)又名高斯分布(Gaussian distribution)

    正态分布(Normal distribution)又名高斯分布(Gaussian distribution),是一个在数学.物理及project等领域都很重要的概率分布,在统计学的很多方面有着重大的影 ...

  8. VC++的内联汇编

    1.移植性差,假设是软件项目建议不要用.假设希望一段程序仅在单一设备上执行而且效率极高,能够使用内联汇编. 比方.单片机开发. 2. ......持续更新中. .... .

  9. swift 关于 toolbar 学习笔记

    import UIKit class ViewController: UIViewController { @IBOutlet weak var toolBar: UIToolbar! @IBOutl ...

  10. BZOJ 1025: [SCOI2009]游戏( 背包dp )

    显然题目要求长度为n的置换中各个循环长度的lcm有多少种情况. 判断一个数m是否是满足题意的lcm. m = ∏ piai, 当∑piai ≤ n时是满足题意的. 最简单我们令循环长度分别为piai, ...