原文地址:/mysweet/archive//08/05/2623687.html
在权限管理中一个很重要的就是关于权限的拦截验证问题,特别是我们在webform中的验证,比纯winform要更复杂,winform可以通过验证把按钮隐藏或者禁用的方式,但是在web中我们不能仅仅通过隐藏按钮,不显示菜单/按钮之类的手段,因为客户端的代码都是透明的,如果我们不在服务端把好关,那么权限根本就无从谈起,我们必须彻底的进行验证,每一步动作都要进行验证,客户端的每一个ajax提交都要进行验证,如果任何一个ajax 动作都做过验证了,那么至少可以保证基本的安全性了.
在纯webform中,我们通常怎么来进行权限控制呢?
一般情况下,设计基类然后,在基类写好验证方法,子类调用并验证
我们来看看启航动力的开源CMS怎么进行的验证:
1: using System;
2: using System.Collections.Generic;
3: using System.Text;
4: using System.Web;
5: using System.Web.UI.WebControls;
6: using mon;
7:
8: namespace DTcms.Web.UI
9: {
10:public class ManagePage : System.Web.UI.Page
11:{
12:protected internal Model.siteconfig siteConfig;
13:
14:public ManagePage()
15:{
16: this.Load += new EventHandler(ManagePage_Load);
17: siteConfig = new BLL.siteconfig().loadConfig(Utils.GetXmlMapPath("Configpath"));
18:}
19:
20:private void ManagePage_Load(object sender, EventArgs e)
21:{
22: //判断管理员是否登录
23: if (!IsAdminLogin())
24: {
25: Response.Write("<script>parent.location.href='" + siteConfig.webpath + siteConfig.webmanagepath + "/login.aspx'</script>");
26: Response.End();
27: }
28:}
29:
30:#region 管理员============================================
31:/// <summary>
32:/// 判断管理员是否已经登录(解决Session超时问题)
33:/// </summary>
34:public bool IsAdminLogin()
35:{
36: //如果Session为Null
37: if (Session[DTKeys.SESSION_ADMIN_INFO] != null)
38: {
39: return true;
40: }
41: else
42: {
43: //检查Cookies
44: string adminname = Utils.GetCookie("AdminName", "DTcms"); //解密用户名
45: string adminpwd = Utils.GetCookie("AdminPwd", "DTcms");
46: if (adminname != "" && adminpwd != "")
47: {
48: BLL.manager bll = new BLL.manager();
49: Model.manager model = bll.GetModel(adminname, adminpwd);
50: if (model != null)
51: {
52:Session[DTKeys.SESSION_ADMIN_INFO] = model;
53:return true;
54: }
55: }
56: }
57: return false;
58:}
59:
60:/// <summary>
61:/// 取得管理员信息
62:/// </summary>
63:public Model.manager GetAdminInfo()
64:{
65: if (IsAdminLogin())
66: {
67: Model.manager model = Session[DTKeys.SESSION_ADMIN_INFO] as Model.manager;
68: if (model != null)
69: {
70: return model;
71: }
72: }
73: return null;
74:}
75:
76:/// <summary>
77:/// 检查管理员权限
78:/// </summary>
79:/// <param name="channel_id">频道ID</param>
80:/// <param name="action_type">操作类型</param>
81:public void ChkAdminLevel(int channel_id, string action_type)
82:{
83: Model.manager model = GetAdminInfo();
84: BLL.manager_role bll = new BLL.manager_role();
85: bool result = bll.Exists(model.role_id, channel_id, action_type);
86: if (!result)
87: {
88: string msbox = "parent.f_errorTab(\"错误提示\", \"您没有管理该页面的权限,请勿尝试非法进入!\")";
89: //ClientScript.RegisterClientScriptBlock(Page.GetType(), "JsPrint", msbox.ToString(), true); //修正BUG
90: Response.Write("<script type=\"text/javascript\">" + msbox + "</script>");
91: Response.End();
92: }
93:}
94:
95:/// <summary>
96:/// 检查管理员权限
97:/// </summary>
98:/// <param name="channel_name">栏目名称</param>
99:/// <param name="action_type">操作类型</param>
100:public void ChkAdminLevel(string channel_name, string action_type)
101:{
102: Model.manager model = GetAdminInfo();
103: BLL.manager_role bll = new BLL.manager_role();
104: bool result = bll.Exists(model.role_id, channel_name, action_type);
105: if (!result)
106: {
107: string msbox = "parent.f_errorTab(\"错误提示\", \"您没有管理该页面的权限,请勿尝试非法进入!\")";
108: //ClientScript.RegisterClientScriptBlock(Page.GetType(), "JsPrint", msbox.ToString(), true); //修正BUG
109: Response.Write("<script type=\"text/javascript\">" + msbox + "</script>");
110: Response.End();
111: }
112:}
113:
114:/// <summary>
115:/// 检查管理员权限
116:/// </summary>
117:/// <param name="channel_name">栏目名称</param>
118:/// <param name="action_type">操作类型</param>
119:/// <returns>bool</returns>
120:public bool IsAdminLevel(string channel_name, string action_type)
121:{
122: Model.manager model = GetAdminInfo();
123: BLL.manager_role bll = new BLL.manager_role();
124: return bll.Exists(model.role_id, channel_name, action_type);
125:}
126:
127:#endregion
128:
129:#region 枚举==============================================
130:
131:/// <summary>
132:/// 统一管理操作枚举
133:/// </summary>
134:public enum ActionEnum
135:{
136: /// <summary>
137: /// 所有
138: /// </summary>
139: All,
140: /// <summary>
141: /// 查看
142: /// </summary>
143: View,
144: /// <summary>
145: /// 添加
146: /// </summary>
147: Add,
148: /// <summary>
149: /// 修改
150: /// </summary>
151: Edit,
152: /// <summary>
153: /// 删除
154: /// </summary>
155: Delete
156:}
157:
158:/// <summary>
159:/// 属性类型枚举
160:/// </summary>
161:public enum AttributeEnum
162:{
163: /// <summary>
164: /// 输入框
165: /// </summary>
166: Text,
167: /// <summary>
168: /// 下拉框
169: /// </summary>
170: Select,
171: /// <summary>
172: /// 单选框
173: /// </summary>
174: Radio,
175: /// <summary>
176: /// 复选框
177: /// </summary>
178: CheckBox
179:}
180:#endregion
181:
182:#region JS提示============================================
183:
184:/// <summary>
185:/// 添加编辑删除提示
186:/// </summary>
187:/// <param name="msgtitle">提示文字</param>
188:/// <param name="url">返回地址</param>
189:/// <param name="msgcss">CSS样式</param>
190:protected void JscriptMsg(string msgtitle, string url, string msgcss)
191:{
192: string msbox = "parent.jsprint(\"" + msgtitle + "\", \"" + url + "\", \"" + msgcss + "\")";
193: ClientScript.RegisterClientScriptBlock(Page.GetType(), "JsPrint", msbox, true);
194:}
195:
196:/// <summary>
197:/// 带回传函数的添加编辑删除提示
198:/// </summary>
199:/// <param name="msgtitle">提示文字</param>
200:/// <param name="url">返回地址</param>
201:/// <param name="msgcss">CSS样式</param>
202:/// <param name="callback">JS回调函数</param>
203:protected void JscriptMsg(string msgtitle, string url, string msgcss, string callback)
204:{
205: string msbox = "parent.jsprint(\"" + msgtitle + "\", \"" + url + "\", \"" + msgcss + "\", " + callback + ")";
206: ClientScript.RegisterClientScriptBlock(Page.GetType(), "JsPrint", msbox, true);
207:}
208:#endregion
209:
210:}
211: }
在子类校验的时候继承ManagePage的基类,然后就这样校验:
可以看到这种是通常的设计方案,基类定义,子类校验,不过这个启航动力CMS,他完全是在基类定义枚举,控制仅仅停留在增删改查,浏览,这些,不过CMS确实这一层就可以了,而且它的设计感觉不太好,因为到处都是验证代码,每一个增删改查方法都有这些验证的代码,如果是我我就会用委托的方式绑定方法,在Page_Load里面验证权限,委托绑定增删改查方法,这样,把验证的过程大大节省,这些甚至可以设计成公共的方法,来实现.
我们今天讲解的是MVC里面的权限验证,MVC天然的Controller,Action,让我们的权限控制更加容易,而且更简洁,更清晰.
首先,先来看看,MVC里面的一个小特色设计:
这个是一个普通的model,在mvc示例项目中,他采用Attribute方式来验证,我当时看到的时候感觉耳目一新,以前看<<CLR VIA C#>> Attribute的时候,当时还在想这些东西可以干什么??仅仅是元数据描述??后来才发现,这东西太强大了,控件的设计,反射,ORM,无处不在,Attributes也让代码更加优雅.
我们可以在mvc中定义各种Attribute来让我们的代码更优雅,而且让权限更简洁,比如我们经常会设计,
xxxx页面登录后才能访问,
xxxxx页面匿名用户也能访问,
xxxx页面必须经过权限验证才能访问,
xxxxx各种类型
我们可以定义各种Attribute来描述它,这种描述也让权限控制更加优雅.
比如:我们有几个登录页面,错误显示页面等等,这些页面,可以单独设计一个Attribute标记来标识.
我们可以定义各种各样的标记来描述权限控制,
可以看到我们在这里只需要标记匿名标记,然后在权限拦截中进行处理,如果存在Anonymous标记就默认允许.
这里在公共基类中设计验证标记,子类继承,这样,我们就可以达到子类全部都需要验证处理..
接下来,我们就看看,我们的权限拦截如何处理的.
我们的权限拦截是通过继承ActionFilterAttribute,自定义拦截器,这里参考传说中弦哥的思路.
简单地说,ActionFilter就是Action过滤器,任何一个请求都像筛子一样的过滤.所以,这个Filter就是筛子,我们需要的就是在这个筛子上做权限控制,这样我们的权限不就容易得多了么?
这时候,我想到了以前的一张生命周期,一个请求过来同样经过了HttpModule等一层层,在那里做权限拦截,可能效果更好,如果webform设计,可能要尝试一下看看能不能这么做.
1: /// <summary>
2:/// 权限拦截
3:/// </summary>
4:[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
5:public class PermissionFilterAttribute : ActionFilterAttribute
6:{
7:/// <summary>
8:/// 权限拦截
9:/// </summary>
10:/// <param name="filterContext"></param>
11:public override void OnActionExecuting(ActionExecutingContext filterContext)
12:{
13: //权限拦截是否忽略
14: bool IsIgnored = false;
15: if (filterContext == null)
16: {
17: throw new ArgumentNullException("filterContext");
18: }
19: var path = filterContext.HttpContext.Request.Path.ToLower();
20: //获取当前配置保存起来的允许页面
21: IList<string> allowPages = ConfigSettings.GetAllAllowPage();
22: foreach (string page in allowPages)
23: {
24: if (page.ToLower() == path)
25: {
26: IsIgnored = true;
27: break;
28: }
29: }
30: if (IsIgnored)
31: return;
32: //接下来进行权限拦截与验证
33: object[] attrs = filterContext.ActionDescriptor.GetCustomAttributes(typeof(ViewPageAttribute), true);
34: var isViewPage = attrs.Length == 1;//当前Action请求是否为具体的功能页
35:
36: if (this.AuthorizeCore(filterContext) == false)//根据验证判断进行处理
37: {
38: //注:如果未登录直接在URL输入功能权限地址提示不是很友好;如果登录后输入未维护的功能权限地址,那么也可以访问,这个可能会有安全问题
39: if (isViewPage == true)
40: {
41: //跳转到登录页面
42: filterContext.RequestContext.HttpContext.Response.Redirect("~/Admin/Manage/UserLogin");
43: }
44: else
45: {
46:
47: //跳转到登录页面
48: filterContext.RequestContext.HttpContext.Response.Redirect("~/Admin/Manage/Error");
49: }
50: }
51:}
这个Attribute直接借鉴的弦哥的模型,
这样我们可以对程序进行细化的处理过程.
针对不同的标记进行处理:
1: /// <summary>
2:/// [Anonymous标记]验证是否匿名访问
3:/// </summary>
4:/// <param name="filterContext"></param>
5:/// <returns></returns>
6:public bool CheckAnonymous(ActionExecutingContext filterContext)
7:{
8: //验证是否是匿名访问的Action
9: object[] attrsAnonymous = filterContext.ActionDescriptor.GetCustomAttributes(typeof(AnonymousAttribute), true);
10: //是否是Anonymous
11: var Anonymous = attrsAnonymous.Length == 1;
12: return Anonymous;
13:}
14:/// <summary>
15:/// [LoginAllowView标记]验证是否登录就可以访问(如果已经登陆,那么不对于标识了LoginAllowView的方法就不需要验证了)
16:/// </summary>
17:/// <param name="filterContext"></param>
18:/// <returns></returns>
19:public bool CheckLoginAllowView(ActionExecutingContext filterContext)
20:{
21: //在这里允许一种情况,如果已经登陆,那么不对于标识了LoginAllowView的方法就不需要验证了
22: object[] attrs = filterContext.ActionDescriptor.GetCustomAttributes(typeof(LoginAllowViewAttribute), true);
23: //是否是LoginAllowView
24: var ViewMethod = attrs.Length == 1;
25: return ViewMethod;
26:}
27:
28:/// <summary>
29:/// //权限判断业务逻辑
30:/// </summary>
31:/// <param name="filterContext"></param>
32:/// <param name="isViewPage">是否是页面</param>
33:/// <returns></returns>
34:protected virtual bool AuthorizeCore(ActionExecutingContext filterContext)
35:{
36:
37: if (filterContext.HttpContext == null)
38: {
39: throw new ArgumentNullException("httpContext");
40: }
41: //验证当前Action是否是匿名访问Action
42: if (CheckAnonymous(filterContext))
43: return true;
44: //未登录验证
45: if (SessionHelper.Get("UserID") == null)
46: {
47: return false;
48: }
49: //验证当前Action是否是登录就可以访问的Action
50: if (CheckLoginAllowView(filterContext))
51: return true;
52:
53: //下面开始用户权限验证
54: var user = new UserService();
55: SysCurrentUser CurrentUser = new SysCurrentUser();
56: var controllerName = filterContext.RouteData.Values["controller"].ToString();
57: var actionName = filterContext.RouteData.Values["action"].ToString();
58: //如果是超级管理员,直接允许
59: if (CurrentUser.UserID == ConfigSettings.GetAdminUserID())
60: {
61: return true;
62: }
63: //如果拥有超级管理员的角色就默认全部允许
64: string AdminUserRoleID = ConfigSettings.GetAdminUserRoleID().ToString();
65: //检查当前角色组有没有超级角色
66: if (Tools.CheckStringHasValue(CurrentUser.UserRoles, ',', CurrentUser.UserRoles))
67: {
68: return true;
69: }
70:
71: //Action权限验证
72: if (controllerName.ToLower() != "manage")//如果当前Action请求为具体的功能页并且不是Manage中 Index页和Welcome页
73: {
74: //验证
75: if (!user.RoleHasOperatePermission(CurrentUser.UserRoles, controllerName, actionName))//如果验证该操作是否拥有权限
76: {
77: return false;
78: }
79: }
80: //管理页面直接允许
81: return true;
82:}
可以看到我们仅仅这一个PermissionAttribute配合其他的Attribute就实现了权限的拦截控制.
当然,我们仍然需要配置那些东西?
过滤页面.....
有一些页面我们可以直接配置允许访问的页面:
1: var path = filterContext.HttpContext.Request.Path.ToLower();
2: //获取当前配置保存起来的允许页面
3: IList<string> allowPages = ConfigSettings.GetAllAllowPage();
4: foreach (string page in allowPages)
5: {
6: if (page.ToLower() == path)
7: {
8: IsIgnored = true;
9: break;
10: }
11: }
12: if (IsIgnored)
13: return;
我们在自定义配置文件中,可以定义允许访问的页面,比如:错误页之类的,可能有些人觉得,不需要,但是这个配置是在程序发布以后,仍然能够很轻松的进行配置,所以,预留一个配置页面还是蛮有必要的.
同时我们也需要配置超级管理员身份和角色....
有人觉得,这些需要么?
我觉得是需要的,因为数据库读取出来的角色,根本没办法分辨超级管理员,只能数据库动态配置,我们就预定义这样的一个超级管理员角色的身份ID,让这个超级管理角色拥有任何的功能和任何的权限,甚至读取数据库的时候,都是读取的所有模块权限,菜单权限.
这样我们的配置工作就非常简单了,特别是数据库没有大部分配置初试信息(比如菜单信息,角色信息,)的时候,我们不需要手动往数据库添加数据,直接在程序中添加就可以了,也算是一个超级管理员身份.
接下来,我们的权限控制基本上就差不多了,现在我们可以安心的写页面了,权限神马东西,跟咱关系就不大了,这样,分工不是更爽,干别人的活才是最纠结的.......
接下来,我们可以继续设计一些公共类来简化我们日常的操作,对于公共类的设计,我觉得要拿出最大的热情与态度,要知道这些是能够真正节省我们时间的东西.
只有设计好它,我们以后才会更快更爽更轻松.
我们经常会遇到这样的代码:
1: /// <summary>
2:/// 保存资料业务
3:/// </summary>
4:/// <param name="context"></param>
5:public void SaveCompany(HttpContext context)
6:{
7://用户json数据读取
8:company Info=new company ();
9:String CompanyStr = context.Request["Company"];
10:string id=context.Request["id"];
11:string pic = context.Request["pic"];
12:if (!Tools.IsValidInput(ref pic, true) || !Tools.IsValidInput(ref id, true))
13:{
14: return;
15:}
16: //图片保存
17://System.IO.StreamWriter sw = new System.IO.StreamWriter(context.Server.MapPath("tzt.txt"), true);
18://sw.Write(CompanyStr);
19://sw.Close();
20://使用Newtonsoft.Json.dll组件解析json对象
21:
22:JObject o = JObject.Parse(CompanyStr);
23:Info.Username = (string)o.SelectToken("Username");
24:if (!new companyBLL().CheckExistUserName(Info.Username))
25:{
26: context.Response.Write(false);
27: return;
28:}
29:Info.Password = (string)o.SelectToken("Password");
30:Info.Name = (string)o.SelectToken("Name");
31:Info.Isrecommend = ((string)o.SelectToken("Isrecommend"))=="true" ? "1" : "0";
32:Info.Fac = (string)o.SelectToken("Fac");
33:Info.Representative = (string)o.SelectToken("Representative");
34:Info.Isshow = ((string)o.SelectToken("Isshow")) == "true" ? "1" : "0";
35:Info.State = ((string)o.SelectToken("State")) == "true" ? "1" : "0";
36:Info.State1 = ((string)o.SelectToken("State1")) == "true" ? "1" : "0";
37:
38:Info.Zipcode = (string)o.SelectToken("Zipcode");
39:Info.QQ = (string)o.SelectToken("QQ");
40:Info.Telephone = (string)o.SelectToken("Telephone");
41:Info.mobilephone = (string)o.SelectToken("mobilephone");
42:Info.Email = (string)o.SelectToken("Email");
43:Info.Address = (string)o.SelectToken("Address");
44:Info.Website = (string)o.SelectToken("Website");
45:Info.Award = (string)o.SelectToken("Award");
46:Info.Introduction = (string)o.SelectToken("Introduction");
47:Info.Picturepath = pic;
48:
49:if (!string.IsNullOrEmpty(id))
50: Info.Id = Convert.ToInt32(id);
51:
52:if (!Info.Id.HasValue)
53:{
54: Info.rank = 0;
55: Info.hit = 0;
56: //执行增加操作
57: new companyBLL().AddNew(Info);
58: SMTP smtp = new SMTP(Info.Email);
59: string webpath = context.Request.Url.Scheme + "://" + context.Request.Url.Authority + System.Web.VirtualPathUtility.ToAbsolute("~/Default.aspx");
60: smtp.Activation(webpath, Info.Name);//发送激活邮件
61:}
62:else
63:{
64: new companyBLL().Update(Info);
65:}
66:
67:
68:}
这是我以前一个电子商务网站项目写的,
我现在看,简直到处都是毛病.......
首先,关于form读取内容占了一大块.......
可以想象,到处都是赋值语句,看到都吐血,再加上一些验证非空,验证函数等等,更是罪加一等的恶劣.
当然我们需要一步一步的解决这些问题,首先是剥离关于表单读取的内容,封装到一个类中,然后在类中进行验证处理.
权限验证中的样例,
验证也没有做大块的处理,不过大家可以注意,可以看到想当的简洁,我们同时需要各种辅助类的设计,强制转化的处理,非空验证的处理,等等,我们直接设计成扩展方法就能达到上图中ObjToIntNULL()的形式, 也不需要ConvertToInt32(xxxxx)的形式来转化了,不是更简洁么?
1: /* 作者: tianzh
2: * 创建时间: /7/22 15:38:20
3: *
4: */
5: using System;
6: using System.Collections.Generic;
7: using System.Linq;
8: using System.Text;
9:
10: namespace mon
11: {
12:/// <summary>
13:/// 强制转化辅助类(无异常抛出)
14:/// </summary>
15:public static class ConvertHelper
16:{
17:#region 强制转化
18:/// <summary>
19:/// object转化为Bool类型
20:/// </summary>
21:/// <param name="obj"></param>
22:/// <returns></returns>
23:public static bool ObjToBool(this object obj)
24:{
25: bool flag;
26: if (obj == null)
27: {
28: return false;
29: }
30: if (obj.Equals(DBNull.Value))
31: {
32: return false;
33: }
34: return (bool.TryParse(obj.ToString(), out flag) && flag);
35:}
36:/// <summary>
37:/// object强制转化为DateTime类型(吃掉异常)
38:/// </summary>
39:/// <param name="obj"></param>
40:/// <returns></returns>
41:public static DateTime? ObjToDateNull(this object obj)
42:{
43: if (obj == null)
44: {
45: return null;
46: }
47: try
48: {
49: return new DateTime?(Convert.ToDateTime(obj));
50: }
51: catch (ArgumentNullException ex)
52: {
53: return null;
54: }
55:}
56:/// <summary>
57:/// int强制转化
58:/// </summary>
59:/// <param name="obj"></param>
60:/// <returns></returns>
61:public static int ObjToInt(this object obj)
62:{
63: if (obj != null)
64: {
65: int num;
66: if (obj.Equals(DBNull.Value))
67: {
68: return 0;
69: }
70: if (int.TryParse(obj.ToString(), out num))
71: {
72: return num;
73: }
74: }
75: return 0;
76:}
77:/// <summary>
78:/// 强制转化为long
79:/// </summary>
80:/// <param name="obj"></param>
81:/// <returns></returns>
82:public static long ObjToLong(this object obj)
83:{
84: if (obj != null)
85: {
86: long num;
87: if (obj.Equals(DBNull.Value))
88: {
89: return 0;
90: }
91: if (long.TryParse(obj.ToString(), out num))
92: {
93: return num;
94: }
95: }
96: return 0;
97:}
98:/// <summary>
99:/// 强制转化可空int类型
100:/// </summary>
101:/// <param name="obj"></param>
102:/// <returns></returns>
103:public static int? ObjToIntNull(this object obj)
104:{
105: if (obj == null)
106: {
107: return null;
108: }
109: if (obj.Equals(DBNull.Value))
110: {
111: return null;
112: }
113: return new int?(ObjToInt(obj));
114:}
115:/// <summary>
116:/// 强制转化为string
117:/// </summary>
118:/// <param name="obj"></param>
119:/// <returns></returns>
120:public static string ObjToStr(this object obj)
121:{
122: if (obj == null)
123: {
124: return "";
125: }
126: if (obj.Equals(DBNull.Value))
127: {
128: return "";
129: }
130: return Convert.ToString(obj);
131:}
132:/// <summary>
133:/// Decimal转化
134:/// </summary>
135:/// <param name="obj"></param>
136:/// <returns></returns>
137:public static decimal ObjToDecimal(this object obj)
138:{
139: if (obj == null)
140: {
141: return 0M;
142: }
143: if (obj.Equals(DBNull.Value))
144: {
145: return 0M;
146: }
147: try
148: {
149: return Convert.ToDecimal(obj);
150: }
151: catch
152: {
153: return 0M;
154: }
155:}
156:/// <summary>
157:/// Decimal可空类型转化
158:/// </summary>
159:/// <param name="obj"></param>
160:/// <returns></returns>
161:public static decimal? ObjToDecimalNull(this object obj)
162:{
163: if (obj == null)
164: {
165: return null;
166: }
167: if (obj.Equals(DBNull.Value))
168: {
169: return null;
170: }
171: return new decimal?(ObjToDecimal(obj));
172:}
173:#endregion
174:
175:}
176: }
一些好的常用的扩展方法同样是一个相当大的改进,对于代码,也更清晰,更简洁,我们同时可以设计一些非空验证等等.
1: #region 判断对象是否为空
2:/// <summary>
3:/// 判断对象是否为空,为空返回true
4:/// </summary>
5:/// <typeparam name="T">要验证的对象的类型</typeparam>
6:/// <param name="data">要验证的对象</param>
7:public static bool IsNullOrEmpty<T>(this T data)
8:{
9: //如果为null
10: if (data == null)
11: {
12: return true;
13: }
14:
15: //如果为""
16: if (data.GetType() == typeof(String))
17: {
18: if (string.IsNullOrEmpty(data.ToString().Trim())||data.ToString ()=="")
19: {
20: return true;
21: }
22: }
23:
24: //如果为DBNull
25: if (data.GetType() == typeof(DBNull))
26: {
27: return true;
28: }
29:
30: //不为空
31: return false;
32:}
33:
34:/// <summary>
35:/// 判断对象是否为空,为空返回true
36:/// </summary>
37:/// <param name="data">要验证的对象</param>
38:public static bool IsNullOrEmpty(this object data)
39:{
40: //如果为null
41: if (data == null)
42: {
43: return true;
44: }
45:
46: //如果为""
47: if (data.GetType() == typeof(String))
48: {
49: if (string.IsNullOrEmpty(data.ToString().Trim()))
50: {
51: return true;
52: }
53: }
54:
55: //如果为DBNull
56: if (data.GetType() == typeof(DBNull))
57: {
58: return true;
59: }
60:
61: //不为空
62: return false;
63:}
64:#endregion
这些东西其实真没有太多难的东西,只是简单的为了追求更简洁更方便而已,磨刀不误砍柴工就是这个道理,思考怎么偷懒才是程序员应该干的事情,不管多么忙都要停下来思考,想想怎么样才能偷懒!
界面上,不太会美工,直接照搬的LigerUI界面!
目前进度已经完成的差不多了,接下来要陆续总结学到的经验与技巧!
我的google code开源网站首页:/p/tzhsweetsourse/ 一直在努力,从未曾放弃,努力学习中..... 追逐吧!奔跑的少年! 拼搏吧!勇敢的心! 有梦想,就有希望! 为梦想而不懈奋斗着!