(转)基于MVC4+EasyUI的Web开发框架形成之旅--基类控制器CRUD的操作
http://www.cnblogs.com/wuhuacong/p/3352016.html
在上一篇随笔中,我对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开发框架形成之旅--基类控制器CRUD的操作的更多相关文章
- 基于MVC4+EasyUI的Web开发框架形成之旅--基类控制器CRUD的操作
在上一篇随笔中,我对Web开发框架的总体界面进行了介绍,其中并提到了我的<Web开发框架>的控制器的设计关系,Web开发框架沿用了我的<Winform开发框架>的很多架构设计思 ...
- 基于MVC4+EasyUI的Web开发框架形成之旅--附件上传组件uploadify的使用
大概一年前,我还在用Asp.NET开发一些行业管理系统的时候,就曾经使用这个组件作为文件的上传操作,在随笔<Web开发中的文件上传组件uploadify的使用>中可以看到,Asp.NET中 ...
- 基于MVC4+EasyUI的Web开发框架形成之旅--总体介绍
最近花了很多时间在重构和进一步提炼Winform开发框架的工作上,加上时不时有一些项目的开发工作,我博客里面介绍Web开发框架的文章比较少,其实以前在单位工作,80%的时间是做Web开发的,很早就形成 ...
- 基于MVC4+EasyUI的Web开发框架形成之旅--MVC控制器的设计
自从上篇<基于MVC4+EasyUI的Web开发框架形成之旅--总体介绍>总体性的概括,得到很多同行的关注和支持,不过上一篇主要是介绍一个总体的界面效果和思路,本系列的文章将逐步介绍其中的 ...
- 基于MVC4+EasyUI的Web开发框架形成之旅--界面控件的使用
在前面介绍了两篇关于我的基于MVC4+EasyUI技术的Web开发框架的随笔,本篇继续介绍其中界面部分的一些使用知识,包括控件的赋值.取值.清空,以及相关的使用. 我们知道,一般Web界面包括的界面控 ...
- 基于MVC4+EasyUI的Web开发框架形成之旅--框架总体界面介绍
在前面介绍了一些关于最新基于MVC4+EasyUI的Web开发框架文章,虽然Web开发框架的相关技术文章会随着技术的探讨一直写下去,不过这个系列的文章,到这里做一个总结,展示一下整体基于MVC4+Ea ...
- 基于MVC4+EasyUI的Web开发框架形成之旅--权限控制
我在上一篇随笔<基于MVC4+EasyUI的Web开发框架形成之旅--框架总体界面介绍>中大概介绍了基于MVC的Web开发框架的权限控制总体思路.其中的权限控制就是分为“用户登录身份验证” ...
- 转--基于MVC4+EasyUI的Web开发框架形成之旅--界面控件的使用
原文 http://www.cnblogs.com/wuhuacong/p/3317223.html 基于MVC4+EasyUI的Web开发框架形成之旅--界面控件的使用 在前面介绍了两篇关于我的基 ...
- 基于MVC4+EasyUI的Web开发框架形成之旅(7)--权限控制
我在上一篇随笔<基于MVC4+EasyUI的Web开发框架形成之旅--框架总体界面介绍>中大概介绍了基于MVC的Web开发框架的权限控制总体思路.其中的权限控制就是分为“用户登录身份验证” ...
随机推荐
- 使用canvas截图网页为图片并解决跨域空白以及模糊问题
前几天给了个需求对浏览器网页进行截图,把网页统计数据图形表等截图保存至用户本地. 首先对于网页截图,我用的是canvas实现,获取你需要截图的模块的div,从而使用canvas对你需要的模块进行截图. ...
- 洛谷 P3178 BZOJ 4034 [HAOI2015]树上操作
题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 ...
- UEditor使用总结(与SpringMVC整合)
最近再弄富文本框,选择了UEditor,原因是:界面漂亮,百度开源的然而, 开启整合之路(怎么做) 1.下载插件 下载只有将插件放在Webapp下,如图 2.修改 导入之后我们就需要修改一些参数已满足 ...
- eclipse断点调试教程
1.断点就是你希望程序运行到哪暂停, 2.断点就是你希望程序运行到哪暂停, 3.断点就是你希望程序运行到哪暂停,断点往往就是你觉得程序可能出错的地方. 设定断点的办法很简单,在你认为出错的那一行的行 ...
- arcgis server10.2.2公布地图基础服务的详细步骤
1.直接打开制作好的.mxd文档,比方这里: 2.打开mxd文档之后.打开菜单:file-share as -services 弹出地图公布服务的界面: 点击publish之后,耐心的等待一段时间,地 ...
- spring学习笔记(22)声明式事务配置,readOnly无效写无异常
在上一节内容中.我们使用了编程式方法来配置事务,这种优点是我们对每一个方法的控制性非常强.比方我须要用到什么事务,在什么位置假设出现异常须要回滚等.能够进行非常细粒度的配置.但在实际开发中.我们可能并 ...
- vmware mac 分辨率设置
1.安装vmware tool 2.关闭虚拟机,在设置中找到显示器项 3.选中“加速3D图形” 4.在监视器中,选中 指定监视器设置,使用任意分辨率 5.如果没有可用分辨率,手动输入,例如 1680* ...
- 一张游览PHP内核迷宫的藏宝图
PHP内核就像一个迷宫,假设没有一个纵览全局的图,仅仅是面对当中的一个点,就会像进了迷宫一样,走着走着就走到了死胡同.在这个迷宫里转悠了非常久之后,近期得到了一张PHP藏宝图.然后看着这张图去游览PH ...
- luogu2441 角色属性树
题目大意:维护一个可查询.修改的树,查询的是一个节点的:离它距离最近的.组成两个节点Key值的质因数存在交集的.祖先节点:修改是修改一个节点的key值. 如果组成两个Key值的质因数存在交集,则两个数 ...
- 轻快的vim(一):移动
断断续续的使用VIM也一年了,会的始终都是那么几个命令,效率极低 前几个星期把Windows换成了Linux Mint,基本上也稳定了下来 就今晚,我已经下定决心开始新的VIM之旅,顺便写一系列的笔记 ...