(转)基于MVC4+EasyUI的Web开发框架形成之旅--MVC控制器的设计
http://www.cnblogs.com/wuhuacong/p/3284628.html
自从上篇《基于MVC4+EasyUI的Web开发框架形成之旅--总体介绍》总体性的概括,得到很多同行的关注和支持,不过上一篇主要是介绍一个总体的界面效果和思路,本系列的文章将逐步介绍其中的细节,本文主要介绍整个Web开发框架中的MVC控制器的设计。在设计之初,我就希望尽可能的减少代码,提高编程模型的统一性。因此希望能够以基类继承的方式,和我Winform开发框架一样,尽可能通过基类,而不是子类的重复代码来实现各种通用的操作。
1、登录控制的控制器基类设计
我们知道,一般我们创建一个MVC的控制器,都是基于Controller这样的基类来实现。如下代码所示。
public class TestController : Controller
{
//
// GET: /Test/ public ActionResult Index()
{
return View();
} }
在我的Winform开发框架里面,用到了泛型的类型,非常方便实现业务逻辑和数据访问基类的设计,控制器是否也可以这样做的呢?
我们知道,一般的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();
}
................
}
2、数据访问业务基类控制器的设计
我在我的Winform开发框架里面,对很多基类都使用泛型进行设计,这样可以传递相应的数据类型到基类里面进行处理,如下面的BLL层的业务对象定义代码如下所示。
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>里面传入了两个参数,定义代码如下所示。
/// <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>里面了。
/// <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开发框架形成之旅--MVC控制器的设计的更多相关文章
- 基于MVC4+EasyUI的Web开发框架形成之旅--MVC控制器的设计
自从上篇<基于MVC4+EasyUI的Web开发框架形成之旅--总体介绍>总体性的概括,得到很多同行的关注和支持,不过上一篇主要是介绍一个总体的界面效果和思路,本系列的文章将逐步介绍其中的 ...
- 基于MVC4+EasyUI的Web开发框架形成之旅--附件上传组件uploadify的使用
大概一年前,我还在用Asp.NET开发一些行业管理系统的时候,就曾经使用这个组件作为文件的上传操作,在随笔<Web开发中的文件上传组件uploadify的使用>中可以看到,Asp.NET中 ...
- 基于MVC4+EasyUI的Web开发框架形成之旅--总体介绍
最近花了很多时间在重构和进一步提炼Winform开发框架的工作上,加上时不时有一些项目的开发工作,我博客里面介绍Web开发框架的文章比较少,其实以前在单位工作,80%的时间是做Web开发的,很早就形成 ...
- 基于MVC4+EasyUI的Web开发框架形成之旅--界面控件的使用
在前面介绍了两篇关于我的基于MVC4+EasyUI技术的Web开发框架的随笔,本篇继续介绍其中界面部分的一些使用知识,包括控件的赋值.取值.清空,以及相关的使用. 我们知道,一般Web界面包括的界面控 ...
- 基于MVC4+EasyUI的Web开发框架形成之旅--框架总体界面介绍
在前面介绍了一些关于最新基于MVC4+EasyUI的Web开发框架文章,虽然Web开发框架的相关技术文章会随着技术的探讨一直写下去,不过这个系列的文章,到这里做一个总结,展示一下整体基于MVC4+Ea ...
- 基于MVC4+EasyUI的Web开发框架形成之旅--基类控制器CRUD的操作
在上一篇随笔中,我对Web开发框架的总体界面进行了介绍,其中并提到了我的<Web开发框架>的控制器的设计关系,Web开发框架沿用了我的<Winform开发框架>的很多架构设计思 ...
- 基于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开发框架的权限控制总体思路.其中的权限控制就是分为“用户登录身份验证” ...
随机推荐
- php第八节课
加载 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.o ...
- 单行函数、表连接(day02)
回顾: 1.数据库介绍 sql: dql: select dml: insert delete update ddl: create drop alter tcl: commit rollback s ...
- 爬虫系列(十一) 用requests和xpath爬取豆瓣电影评论
这篇文章,我们继续利用 requests 和 xpath 爬取豆瓣电影的短评,下面还是先贴上效果图: 1.网页分析 (1)翻页 我们还是使用 Chrome 浏览器打开豆瓣电影中某一部电影的评论进行分析 ...
- States of Integrity Constraints
States of Integrity Constraints As part of constraint definition, you can specify how and when Oracl ...
- linux 中使用iptables 防止ddocs及cc攻击配置 。
#防止SYN攻击,轻量级预防 iptables -N syn-floodiptables -A INPUT -p tcp –syn -j syn-floodiptables -I syn-flood ...
- Spring事务的传播行为分析
前言 最近项目有涉及到Spring事务,所以工作之余,想认真了解学习下Spring事务,查阅了若干资料,做了一个demo(PS:参考了大牛的). 现分享总结如下: 1.Spring 事务的简介 理解事 ...
- S 禁止F12和右键操作控制台,兼容各浏览器
document.oncontextmenu = function () { return false; }; document.onkeydown = function () { ...
- 【cocos2d-x 3.7 飞机大战】 决战南海I (八) 背景移动
採用双层背景.这样效果更好 .h class BackgroundMove : public Layer { public: BackgroundMove(); ~BackgroundMove(); ...
- JPA相关注解
JPA注解 一.基本注解 1.表相关 @Entity 仅仅要加了这个注解就具备了表和实体的映射关系,表名就是实体名 @Table(name="表名") 一般和实体 ...
- C#调用C++回调函数的问题
C++的回调函数中有一个参数是,是返回一个字符串,原则如下: typedef void (*TDataEvent)(char *AData ,int ALen); 其中char ...