自从上篇《基于MVC4+EasyUI的Web开发框架造成之旅--整体介绍》整体性的归纳,获得不少同行的关注和支持,不过上一篇主要是介绍一个整体的界面效果和思路,本系列的文章将逐步介绍其中的细节,本文主要介绍整个Web开发框架中的MVC控制器的设计。在设计之初,我就但愿尽量的减小代码,提升编程模型的统一性。所以但愿可以以基类继承的方式,和我Winform开发框架同样,尽量经过基类,而不是子类的重复代码来实现各类通用的操做。javascript
咱们知道,通常咱们建立一个MVC的控制器,都是基于Controller这样的基类来实现。以下代码所示。html
public class TestController : Controller { // // GET: /Test/ public ActionResult Index() { return View(); } }
在个人Winform开发框架里面,用到了泛型的类型,很是方便实现业务逻辑和数据访问基类的设计,控制器是否也能够这样作的呢?java
咱们知道,通常的MVC控制器须要验证用户是否已经登录了,这也是不少常见Web操做前的验证,还有对异常的处理,在MVC的基类,能够一并进行记录(这个很是不错),因而咱们先来设计一个验证用户身份是否登录的基类BaseController数据库
/// <summary> /// 全部须要进行登陆控制的控制器基类 /// </summary> public class BaseController : Controller { /// <summary> /// 当前登陆的用户属性 /// </summary> public UserInfo CurrentUserInfo { get; set; } /// <summary> /// 从新基类在Action执行以前的事情 /// </summary> /// <param name="filterContext">重写方法的参数</param> protected override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); //获得用户登陆的信息 CurrentUserInfo = Session["UserInfo"] as UserInfo; //判断用户是否为空 if (CurrentUserInfo == null) { Response.Redirect("/Login/Index"); } } protected override void OnException(ExceptionContext filterContext) { base.OnException(filterContext); //错误记录 WHC.Framework.Commons.LogTextHelper.Error(filterContext.Exception); // 当自定义显示错误 mode = On,显示友好错误页面 if (filterContext.HttpContext.IsCustomErrorEnabled) { filterContext.ExceptionHandled = true; this.View("Error").ExecuteResult(this.ControllerContext); } }
........................ }
有了这个基类,咱们在主页的Home控制类,就可使用用户信息对象了进行操做了,并且必需要求客户登录了。编程
public class HomeController : BaseController { public ActionResult Index() { if (CurrentUserInfo != null) { ViewBag.FullName = CurrentUserInfo.FullName; ViewBag.Name = CurrentUserInfo.Name; } return View(); } ................ }
我在个人Winform开发框架里面,对不少基类都使用泛型进行设计,这样能够传递相应的数据类型到基类里面进行处理,以下面的BLL层的业务对象定义代码以下所示。json
namespace WHC.Security.BLL { /// <summary> /// 角色信息业务管理类 /// </summary> public class Role : BaseBLL<RoleInfo> { ....................
/// <summary> /// 业务基类对象 /// </summary> /// <typeparam name="T">业务对象类型</typeparam> public class BaseBLL<T> where T : BaseEntity, new() { /// <summary> /// 插入指定对象到数据库中 /// </summary> /// <param name="obj">指定的对象</param> /// <returns>执行操做是否成功。</returns> public virtual bool Insert(T obj) { return baseDal.Insert(obj); } ............
业务对象Role,要求传入RoleInfo给基类处理,这样基类就能定义到都对应的T为具体的RoleInfo类型了。在MVC的控制器是否也能够这样作呢?固然能够,下面是我定义的一个控制器继承关系图。框架
上面的介绍也已经比较明白了,其实就是在BusinessController<B, T>里面传入了两个参数,定义代码以下所示。dom
/// <summary> /// 本控制器基类专门为访问数据业务对象而设的基类 /// </summary> /// <typeparam name="B">业务对象类型</typeparam> /// <typeparam name="T">实体类类型</typeparam> public class BusinessController<B, T> : BaseController where B : class where T : WHC.Framework.ControlUtil.BaseEntity, new() { /// <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); } ................
我根据传入的BLL业务对象类型B,对象实体类类型T,那么咱们就能够构造对应的baseBLL对象,而后调用其基类接口实现基本的操做,如插入,删除,更新,查找等等,这样的模式就和个人Winform开发框架的理念很是吻合了。异步
咱们以角色控制器来讲明,它的定义以下所示,若是不须要实现额外的接口(除了常见的操做),基本上不须要写任何代码了,由于全部不少常见的操做,都已经封装在了基类控制器BusinessController<B, T>里面了。ide
/// <summary> /// 角色业务操做控制器 /// </summary> public class RoleController : BusinessController<Role, RoleInfo> { public RoleController() : base() { } ...............
对于一些须要特殊数据处理的操做,能够增长一些自定义的接口函数,也能够重写基类的一些接口,实现数据的相应处理。如个人菜单界面显示中,须要根据缩进的层级对菜单名称进行缩进,以便更好的展现它们的层级结构,那么我就须要对分页函数进行重写了,以下代码所示是整个菜单Menu类的控制器类代码。
public class MenuController : BusinessController<Menu, MenuInfo> { public override ActionResult FindWithPager() { string where = GetPagerCondition(); //基类实现 PagerInfo pagerInfo = GetPagerInfo(); //基类实现 List<MenuInfo> list = baseBLL.FindWithPager(where, pagerInfo); list = CollectionHelper<MenuInfo>.Fill("-1", 0, list, "PID", "ID", "Name"); //Json格式的要求{total:22,rows:{}} //构形成Json的格式传递 var result = new { total = pagerInfo.RecordCount, rows = list }; return JsonDate(result); } /// <summary> /// 用做下拉列表的菜单Json数据 /// </summary> /// <returns></returns> public ActionResult GetDictJson() { List<MenuInfo> list = baseBLL.GetAll(); list = CollectionHelper<MenuInfo>.Fill("-1", 0, list, "PID", "ID", "Name"); List<CListItem> itemList = new List<CListItem>(); foreach (MenuInfo info in list) { itemList.Add(new CListItem(info.Name, info.ID)); } return Json(itemList, JsonRequestBehavior.AllowGet); } }
咱们来看看一段HTML页面里面,使用javascript脚本调用控制器API来实现数据的绑定的操做,也就是使用示例。
$.getJSON("/Role/FindById?r=" + Math.random() + "&id=" + id, function (json) { $("#txtID").val(json.ID); $("#txtName").val(json.Name); $("#txtNote").val(json.Note); });
上面这个很标准的接口FindById是业务基类控制器BusinessController<B, T>里提供的。
固然,BusinessController里面能够相似我Winform开发框架里面基类同样,提供很丰富的操做接口,如返回列表Json集合,增删改查的操做及返回,分页数据的返回,以及一些特殊的操做均可以实现。而这些都不须要子类进行任何实现。
以下面实际案例的用户登录日志,里面的界面功能仍是很丰富的,当他的控制器业务类不须要任何实现,只须要继承基类便可。
public class LoginLogController : BusinessController<LoginLog, LoginLogInfo> { public LoginLogController() : base() { } }
界面部分代码以下所示。
//实现对DataGird控件的绑定操做
function InitGrid(queryData) {
$('#grid').datagrid({ //定位到Table标签,Table标签的ID是grid
url: '/LoginLog/FindWithPager', //指向后台的Action来获取当前用户的信息的Json格式的数据
title: '用户登录日志',
//下面的这些属性若是谁不太清楚的话我建议去官方网站去学习
iconCls: 'icon-view',
height: 450,
nowrap: true,
autoRowHeight: false,
striped: true,
collapsible: true,
pagination: true,
rownumbers: true,
//sortName: 'ID', //根据某个字段给easyUI排序
sortOrder: 'asc',
remoteSort: false,
idField: 'ID',
queryParams: queryData, //异步查询的参数
columns: [[
{ field: 'ck', checkbox: true }, //选择
{ title: 'ID', field: 'ID', width: 40, sortable: true }, //主键
{ title: '登陆用户ID', field: 'User_ID', width: 80, sortable: true },
{ title: '登陆名称', field: 'LoginName', width: 80, sortable: true },
{ title: '真实名称', field: 'FullName', width: 80, sortable: true },
{ title: '日志描述', field: 'Note', width: 100, sortable: true },
{ title: 'IP地址', field: 'IPAddress', width: 100, sortable: true },
{ title: 'Mac地址', field: 'MacAddress', width: 120, sortable: true },
{ title: '系统编号', field: 'SystemType_ID', width: 120, sortable: true },
{ title: '记录日期', field: 'LastUpdated', width: 120, sortable: true },
]],
toolbar: [{
id: 'btnAdd',
text: '添加',
iconCls: 'icon-add',
handler: function () {
ShowAddDialog();//实现添加记录的页面
}
}, '-', {
id: 'btnEdit',
text: '修改',
iconCls: 'icon-edit',
handler: function () {
ShowEditOrViewDialog();//实现修改记录的方法
}
}, '-', {
id: 'btnDelete',
text: '删除',
iconCls: 'icon-remove',
handler: function () {
Delete();//实现直接删除数据的方法
}
}, '-', {
id: 'btnView',
text: '查看',
iconCls: 'icon-table',
handler: function () {
ShowEditOrViewDialog("view");//实现查看记录详细信息的方法
}
}, '-', {
id: 'btnReload',
text: '刷新',
iconCls: 'icon-reload',
handler: function () {
//实现刷新栏目中的数据
$("#grid").datagrid("reload");
}
}]
});
$('#grid').datagrid({
onDblClickRow: function (rowIndex, rowData) {
$('#grid').datagrid('uncheckAll');
$('#grid').datagrid('checkRow', rowIndex);
ShowEditOrViewDialog();
}
});
}
这个就是个人控制器设计的中心思想了,下一篇继续介绍总体的MVC系列的Web开发框架,介绍其中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处理数据交互的几种方式