基于MVC4+EasyUI的Web开发框架形成之旅--基类控制器CRUD的操作

简介:

在上一篇随笔中,我对Web开发框架的总体界面进行了介绍,其中并提到了我的《Web开发框架》的控制器的设计关系,Web开发框架沿用了我的《Winform开发框架》的很多架构设计思路和特点,对Controller进行了封装。使得控制器能够获得很好的继承关系,并能以更少的代码,更高效的开发效率,实现Web项目的开发工作,整个控制器的设计思路如下所示。

从上图的设计里面可以看到,我把主要能通过抽象封装的CRUD方法都放到了BusinessController<B, T>类里面,本文继续详细介绍这个Web框架控制器类的CRUD具体实现,以便使得大家了解我的整个Web开发框架的基类控制器的工作原理。

1、基类的插入操作

我们知道,一般常规的插入操作是很普遍的操作,那么我们在MVC的Web界面上是如何调用的,后台又是如何进行数据的处理的呢?

在MVC的View视图代码里面,我们添加数据的时候,javascript脚本代码是这样的:

                var postData = $("#ffAdd").serializeArray();
                $.post("/Information/Insert", postData, function (data) {
                    if (data = "true") {
                        //添加成功  1.关闭弹出层,2.刷新DataGird
                        $.messager.alert("提示", "添加成功");
                        $("#DivAdd").dialog("close");
                        $("#grid").datagrid("reload");
                        $("#ffAdd").form("clear");

                        //本页面的类型为【通知公告】,固定不变
                        $("#Category").val("通知公告");
                    }
                    else {
                        $.messager.alert("提示", "添加失败,请您检查");
                    }
                });

其中的serializeArray就把该表单要提交的数据序列号到一个字符串里面了,里面的数据可能类似A=a&B=b&C=c 这样的字符串里面了,通过POST调用控制器Information的Insert方法,实现数据的插入。由于控制器Information是具体业务类,因此它继承自BusinessController<B, T>,也就是会调用BusinessController<B, T>控制器的Insert方法。

如字典数据添加的界面如下所示。

那么后台的接收方法如何呢?其实后台是把数据序列化到了一个FormCollection对象的集合里面了,但是,我们还可以使用对象T(实体类),让这些数据集合赋值给对应的实体对象属性,如下就是我的后台控制器的插入方法,它的参数是一个实体类T,这样我们直接调用业务操作类就可以插入了,代码很简单易懂。

        /// <summary>
        /// 插入指定对象到数据库中
        /// </summary>
        /// <param name="info">指定的对象</param>
        /// <returns>执行操作是否成功。</returns>
        public virtual ActionResult Insert(T info)
        {bool result = false;
            if (info != null)
            {
                result = baseBLL.Insert(info);
            }
            return Content(result);
        }

2、基类的更新操作

上面我们看了插入数据的操作,可能大家对下面介绍的数据更新操作,可能也已经有了一些了解了,其实它和插入操作的方法很类似的。

更新操作的视图View中脚本代码如下所示, 它通过控制器Information的Update方法进行更新数据。

                var ID = $("#ID1").val();
                var postData = $("#ffEdit").serializeArray();
                $.post("/Information/Update?ID=" + ID, postData, function (date) {
                    if (date == "true") {
                        //修改成功,关闭弹出层,刷新DataGird
                        $.messager.alert("提示", "修改成功");
                        $("#DivEdit").dialog('close');
                        $("#grid").datagrid("reload");
                    }
                    else {
                        $.messager.alert("提示", "修改失败,请您检查");
                    }
                });

由于控制器Information是具体业务类,因此它继承自BusinessController<B, T>,也就是会调用BusinessController<B, T>控制器的Update方法。

和上面的插入操作一样,后台是把数据序列化到了一个FormCollection对象的集合里面了,我们可以使用类似和插入方法的操作,如下所示。

        /// <summary>
        /// 更新对象属性到数据库中
        /// </summary>
        /// <param name="info">指定的对象</param>
        /// <param name="id">主键ID的值</param>
        /// <returns>执行成功返回<c>true</c>,否则为<c>false</c></returns>
        public virtual ActionResult Update(T info, string id)
        {
            bool result = baseBLL.Update(info, id);
            return Content(result);
        }

但是,如果使用以上的代码作为更新数据的代码,那么在编辑界面里,如果只是显示编辑部分表的数据,那么可能导致很多属性会被初始化为实体类的默认值,显然这样不符合我们的要求,我们可能只是进行部分更新,那么我们进行部分更新的控制器方法应该如何设计呢?

前面我们说到,数据会被序列号到一个FormCollection对象集合里面,更新方法也一样,那么我们可以把更新操作的接口定义为如下代码所示,视图操作代码不变化:

        /// <summary>
        /// 更新对象属性到数据库中
        /// </summary>
        /// <param name="info">指定的对象</param>
        /// <param name="id">主键ID的值</param>
        /// <returns>执行成功返回<c>true</c>,否则为<c>false</c></returns>
        public virtual ActionResult Update(string id, FormCollection formValues)

我们可以通过调试的方法,查询到FormCollection里面的值就是我们更新界面里面的数据(注意:可能是实体类的部分数据)。但使用了这个方法后,我们还需要把FormCollection对象里面的数据转换为实体类的信息,我们才好调用BaseBLL里面的接口进行更新数据。但是不同的实体类,有不同的属性,我们如何能够抽象把他们的属性都赋值了呢?

答案是通过反射属性方式,把FormCollection里面属性的值赋值给对应实体类属性的值。下面我们来介绍下具体的代码实现了。

        /// <summary>
        /// 更新对象属性到数据库中
        /// </summary>
        /// <param name="info">指定的对象</param>
        /// <param name="id">主键ID的值</param>
        /// <returns>执行成功返回<c>true</c>,否则为<c>false</c></returns>
        public virtual ActionResult Update(string id, FormCollection formValues)
        {

            T obj = baseBLL.FindByID(id);
            if (obj != null)
            {
                //遍历提交过来的数据(可能是实体类的部分属性更新)
                foreach (string key in formValues.Keys)
                {
                    string value = formValues[key];
                    System.Reflection.PropertyInfo propertyInfo = obj.GetType().GetProperty(key);
                    if (propertyInfo != null)
                    {
                        try
                        {
                            // obj对象有key的属性,把对应的属性值赋值给它(从字符串转换为合适的类型)
                            //如果转换失败,会抛出InvalidCastException异常
                            propertyInfo.SetValue(obj, Convert.ChangeType(value, propertyInfo.PropertyType), null);
                        }
                        catch { }
                    }
                }
            }

            bool result = baseBLL.Update(obj, id);
            return Content(result);
        }

通过对象propertyInfo的SetValue方法,可以把字符串的值,转换为实体类对应属性类型的值,顺利进行赋值。

如果是业务类需要提交一些HTML的代码,那么我们需要在具体的业务类里面,重写插入、更新方法并设置一下 [ValidateInput(false)] 标识才可以。

        [ValidateInput(false)]
        public override ActionResult Insert(InformationInfo info)
        {
            info.Editor = CurrentUser.Name;
            info.EditTime = DateTime.Now;

            return base.Insert(info);
        }

        [ValidateInput(false)]
        public override ActionResult Update(string id, FormCollection formValues)
        {
            return base.Update(id, formValues);
        }

如通知公告的内容编辑界面如下所示。

3、基类的获取对象数据方法

我们在很多接口里面,都要求获取单一对象的数据信息,我在基类接口里面定义了一个FindByID方法,就是从业务对象里面,根据主键ID信息,获取一个对象的数据,把他转换为Json传递到View视图里面使用即可。

        /// <summary>
        /// 查询数据库,检查是否存在指定ID的对象
        /// </summary>
        /// <param name="id">对象的ID值</param>
        /// <returns>存在则返回指定的对象,否则返回Null</returns>
        public virtual ActionResult FindByID(string id)
        {
            ActionResult result = Content("");
            T info = baseBLL.FindByID(id);
            if (info != null)
            {
                result = JsonDate(info);
            }

            return result;
        }

其中的JsonDate方法是为了避免日期类型的数值在序列化中出现错误格式,包装的一个方法,如下所示。

        /// <summary>
        /// 返回处理过的时间的Json字符串
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public ContentResult JsonDate(object date)
        {
            var timeConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" };
            return Content(JsonConvert.SerializeObject(date, Formatting.Indented, timeConverter));
        }

在View视图里面使用控制器方法,绑定数据到查看界面里面的代码如下所示。

        //绑定查看详细信息的方法
        function BindViewInfo() {
            var ID = $("#grid").datagrid('getSelections')[0].ID;            
            //发送请求
            $.getJSON("/Information/FindByID?r=" + Math.random() + "&id=" + ID, function (info) {
                $("#ID2").val(info.ID);
                $("#Title2").text(info.Title);
                $("#Content2").html(info.Content);
                $("#Attachment_GUID2").text(info.Attachment_GUID);
                $("#Editor2").text(info.Editor);
                $("#EditTime2").text(info.EditTime);

                ShowUpFiles(info.Attachment_GUID, 'divViewAttach');
            });
        }

具体效果如下所示:

4、基类删除操作方法

在GridView里面,我们提供了删除数据的按钮,具体视图里面使用的代码如下所示。

                //然后确认发送异步请求的信息到后台删除数据
                $.messager.confirm("删除确认", "您确认删除选定的记录吗?", function (deleteAction) {
                    if (deleteAction) {
                        $.get("/Information/DeletebyIds", postData, function (data) {
                            if (data == "true") {
                                $.messager.alert("提示", "删除选定的记录成功");
                                $("#grid").datagrid("reload");
                            }
                            else {
                                $.messager.alert("提示", data);
                            }
                        });
                    }
                });

后台控制器的基类删除方法如下所示。

        /// <summary>
        /// 删除多个ID的记录
        /// </summary>
        /// <param name="ids">多个id组合,逗号分开(1,2,3,4,5)</param>
        /// <returns></returns>
        public virtual ActionResult DeleteByIds(string ids)
        {bool result = false;
            if (!string.IsNullOrEmpty(ids))
            {
                string[] idArray = ids.Split(new char[] { ',' });
                foreach (string strId in idArray)
                {
                    if (!string.IsNullOrEmpty(strId))
                    {
                        baseBLL.Delete(strId);
                    }
                }
                result = true;
            }
            return Content(result);
        } 

以上就是基类控制器增删改查的一些通用方法的封装,业务对象控制器类,如果有特殊的需要,可以对方法进行重写即可,非常方便使用,从而减少了很多重复编写的代码,并可以使得页面的操作统一化,提高生产效率。

基于MVC4+EasyUI的Web开发框架的系列文章:

基于MVC4+EasyUI的Web开发框架形成之旅--总体介绍

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

基于MVC4+EasyUI的Web开发框架形成之旅--界面控件的使用

基于MVC4+EasyUI的Web开发框架形成之旅--附件上传组件uploadify的使用

基于MVC4+EasyUI的Web开发框架形成之旅--框架总体界面介绍

基于MVC4+EasyUI的Web开发框架形成之旅--基类控制器CRUD的操作

基于MVC4+EasyUI的Web开发框架形成之旅--权限控制

基于MVC4+EasyUI的Web开发框架经验总结(1)-利用jQuery Tags Input 插件显示选择记录

基于MVC4+EasyUI的Web开发框架经验总结(2)- 使用EasyUI的树控件构建Web界面

基于MVC4+EasyUI的Web开发框架经验总结(3)- 使用Json实体类构建菜单数据

基于MVC4+EasyUI的Web开发框架经验总结(4)--使用图表控件Highcharts

基于MVC4+EasyUI的Web开发框架经验总结(5)--使用HTML编辑控件CKEditor和CKFinder

基于MVC4+EasyUI的Web开发框架经验总结(6)--在页面中应用下拉列表的处理

基于MVC4+EasyUI的Web开发框架经验总结(7)--实现省份、城市、行政区三者联动

基于MVC4+EasyUI的Web开发框架经验总结(8)--实现Office文档的预览

基于MVC4+EasyUI的Web开发框架经验总结(9)--在Datagrid里面实现外键字段的转义操作

基于MVC4+EasyUI的Web开发框架经验总结(10)--在Web界面上实现数据的导入和导出

基于MVC4+EasyUI的Web开发框架经验总结(11)--使用Bundles处理简化页面代码

基于MVC4+EasyUI的Web开发框架经验总结(12)--利用Jquery处理数据交互的几种方式

基于MVC4+EasyUI的Web开发框架经验总结(13)--DataGrid控件实现自动适应宽带高度

基于MVC4+EasyUI的Web开发框架经验总结(14)--自动生成图标样式文件和图标的选择操作

本文转自博客园伍华聪的博客,原文链接:基于MVC4+EasyUI的Web开发框架形成之旅--基类控制器CRUD的操作,如需转载请自行联系原博主。



目录
相关文章
|
12月前
|
开发框架 JSON API
震撼发布!Python Web开发框架下的RESTful API设计全攻略,让数据交互更自由!
【7月更文挑战第22天】在Python Web开发中,设计高效的RESTful API涉及选择框架(如Flask或Django)、明确资源及使用HTTP方法(GET, POST, PUT, DELETE)来操作数据。响应格式通常是JSON,错误处理也很重要。示例展示了使用Flask创建图书管理API,包括版本控制、文档化、安全性和性能优化是最佳实践。这样的API使数据交互更顺畅。
153 2
|
设计模式 存储 前端开发
MVC(模型-视图-控制器)是一种在Web应用程序开发中广泛使用的软件设计模式
【5月更文挑战第12天】MVC模式是Web应用开发中的常见设计模式,将逻辑、数据和界面分离,提升代码可维护性和重用性。模型处理数据逻辑,视图展示数据,控制器协调用户输入与模型视图交互。优点包括代码分离、易维护、可扩展和组件重用,促进高效灵活的开发。
143 2
|
文字识别 前端开发 API
视觉智能开放平台产品使用合集之需要在Web端处理本地文件并上传,该如何操作
视觉智能开放平台是指提供一系列基于视觉识别技术的API和服务的平台,这些服务通常包括图像识别、人脸识别、物体检测、文字识别、场景理解等。企业或开发者可以通过调用这些API,快速将视觉智能功能集成到自己的应用或服务中,而无需从零开始研发相关算法和技术。以下是一些常见的视觉智能开放平台产品及其应用场景的概览。
|
11月前
|
前端开发 关系型数据库 MySQL
Python基于Django框架图书管理系统,Bootstrap框架UI,后台EasyUI框架UI,有登录,实现增删改查的富文本效果
本文介绍了一个使用Python Django框架开发的图书管理系统,该系统采用Bootstrap框架进行前端UI设计,EasyUI框架用于后台UI界面,集成了富文本编辑器,并实现了登录及增删改查功能。
241 1
|
数据采集 Web App开发 前端开发
Selenium:自动化Web浏览器操作的强大工具
**Selenium** 是一款用于自动化Web应用测试和模拟用户行为的工具,支持多种浏览器和编程语言。安装包括安装Selenium库和对应浏览器的WebDriver。基本用法包括导入库、启动浏览器、查找与操作页面元素、等待元素加载及关闭浏览器。在实际项目中,Selenium常用于Web测试、爬虫、自动化表单填写等,优点是跨平台、模拟真实用户行为,但性能较低且依赖浏览器。
630 9
|
11月前
|
设计模式 开发框架 前端开发
使用 FastEndpoints 来垂直切割Web API的控制器方法
使用 FastEndpoints 来垂直切割Web API的控制器方法
|
机器学习/深度学习 人工智能 Apache
人工智能平台PAI操作报错合集之alink任务可以在本地运行,上传到flink web运行就报错,如何解决
阿里云人工智能平台PAI (Platform for Artificial Intelligence) 是阿里云推出的一套全面、易用的机器学习和深度学习平台,旨在帮助企业、开发者和数据科学家快速构建、训练、部署和管理人工智能模型。在使用阿里云人工智能平台PAI进行操作时,可能会遇到各种类型的错误。以下列举了一些常见的报错情况及其可能的原因和解决方法。
|
前端开发 计算机视觉
视觉智能开放平台操作报错合集之人脸对比1:1,采用web前端直接调用,使用了base64处理图片,提示http错误码414,该如何处理
在使用视觉智能开放平台时,可能会遇到各种错误和问题。虽然具体的错误代码和消息会因平台而异,但以下是一些常见错误类型及其可能的原因和解决策略的概述,包括但不限于:1. 认证错误、2. 请求参数错误、3. 资源超限、4. 图像质量问题、5. 服务不可用、6. 模型不支持的场景、7. 网络连接问题,这有助于快速定位和解决问题。
143 0
|
移动开发 开发框架 JavaScript
技术心得记录:手机Web开发框架
技术心得记录:手机Web开发框架
135 0
|
前端开发 程序员 API
视觉智能开放平台产品使用合集之web前端拉起人脸识别该如何操作
视觉智能开放平台是指提供一系列基于视觉识别技术的API和服务的平台,这些服务通常包括图像识别、人脸识别、物体检测、文字识别、场景理解等。企业或开发者可以通过调用这些API,快速将视觉智能功能集成到自己的应用或服务中,而无需从零开始研发相关算法和技术。以下是一些常见的视觉智能开放平台产品及其应用场景的概览。

热门文章

最新文章