在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、数据信息的展示

一般情况下,我们在界面里面展示的信息是相对比较丰富的,尽管我们设计数据表的时候,考虑的是如何精简且避免重复,但是在界面上展示的信息,往往是考虑如何让用户更加方便,因此可能尽可能的展示相关信息。

如对于这样的场景,设备信息作为主要的基础信息,其相关的业务包括设备检查、设备维护、设备报修等信息,如下所示。

基于上面的数据设计,我们如果在展示设备检查、设备维护、设备报修等信息的时候,那么我们一般还需要展示部分的设备基础信息,这样我们更容易了解整个记录数据,但是我们在数据设计的时候,是把它们分开的,因此需要在输出到界面的时候,把它们综合起来。

我以前在《基于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,实现数据转义的输出,如需转载请自行联系原博主。

 

时间: 2024-07-29 15:34:05

在MVC控制器里面使用dynamic和ExpandoObject,实现数据转义的输出的相关文章

学习php过程中发现mvc控制器要写几个页面

问题描述 学习php过程中发现mvc控制器要写几个页面 零基础看视频自学中 看到老师讲mvc模式控制器 说写到一个界面最好 可是我发现如果把insert和update写到一个界面里的话 每次update的时候就要insert一下如果定义不同的post值的话又会报错 难道要用if判断一下是否有这个值吗 那样的话不是又比较臃肿了吗 请问各位是怎么解决的 还是要多写几个页面每个页面控制一下的好? 解决方案 写在一个页面是一个偷懒的办法, 在正式的项目中不建议这么做,虽然有判断可以区分,但是容易出错.

ASP.NET在MVC控制器中获取Form表单值的方法_实用技巧

本文实例讲述了ASP.NET在MVC控制器中获取Form表单值的方法.分享给大家供大家参考,具体如下: 在MVC控制器中,如果我们想直接获取表单中某个标签元素的值,可以使用MVC中提供的FormCollection类,具体用法如下所示: 视图部分: @using (Html.BeginForm()) { <text>您输入的值是:</text><span>@ViewBag.FormValue</span> <input type="text&

基于MVC4+EasyUI的Web开发框架形成之旅--MVC控制器的设计

自从上篇<基于MVC4+EasyUI的Web开发框架形成之旅--总体介绍>总体性的概括,得到很多同行的关注和支持,不过上一篇主要是介绍一个总体的界面效果和思路,本系列的文章将逐步介绍其中的细节,本文主要介绍整个Web开发框架中的MVC控制器的设计.在设计之初,我就希望尽可能的减少代码,提高编程模型的统一性.因此希望能够以基类继承的方式,和我Winform开发框架一样,尽可能通过基类,而不是子类的重复代码来实现各种通用的操作. 1.登录控制的控制器基类设计 我们知道,一般我们创建一个MVC的控制

mvc get无刷新页面绑定table中数据

问题描述 mvc get无刷新页面绑定table中数据 我刚接触MVC 我想使用GET方式对Tbale中的数据进行刷新?get方式最好可以返回的是ViewBag?谁弄过啊???

javaweb-spring mvc接收不到put方式提交的数据

问题描述 spring mvc接收不到put方式提交的数据 在做修改的时候,提交的方式是put请求,然后spring mvc中的一个方法处理请求,接收参数是一个实体bean,但是这个接收参数就是接收不到提交的数据不知道除了过滤器能解决还有什么办法没有? 解决方案 spring MVC 接收PUT方式请求关于HTTP提交方式之PUT让spring mvc支持put请求 解决方案二: 假设方法为,接受的参数为User实体类 public void Test1(){} 第一种方式为: public v

pring easyui-Spring MVC easyui1.3.2 datagrid无法加载数据

问题描述 Spring MVC easyui1.3.2 datagrid无法加载数据 jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@include file="/common/page/jqueryMaster.jsp"%> <!DOCTYPE html P

MVC+LINQToSQL的Repository模式之(二)数据基类

namespace Data.TEST{    /// <summary>    /// 数据操作基类    /// </summary>    public abstract class TESTRepositoryBase    {        /// <summary>        /// 数据库基类        /// </summary>        protected Entity.TEST.LinqTESTDataContext _db

MVC+LINQToSQL的Repository模式之(四)数据统一更新的附加类

namespace public static class DynamicQueryable public static IQueryablethis IQueryablestring params objectreturn IQueryableIQueryablepublic static IQueryable this IQueryable string params objectif nullthrow new ArgumentNullException"source"if nu

PetaPoco支持Dynamic(ExpandoObject)类型参数

修改ParametersHelper类,添加ExpandoObject的类型判断吧,修改后的代码如下: // PetaPoco - A Tiny ORMish thing for your POCO's. // Copyright 2011-2012 Topten Software. All Rights Reserved. using System; using System.Collections.Generic; using System.Text.RegularExpressions;