asp.net实现非常实用的自定义页面基类(附源码)
本文实例讲述了asp.net实现非常实用的自定义页面基类。分享给大家供大家参考,具体如下:
看到前面几篇文章(如:《asp.net实现利用反射,泛型,静态方法快速获取表单值到model的方法》)想到的。下面总结发布一个笔者在开发中常用的一个自定义basepage类,废话不多说了,直接贴代码。
一、basepage类
1、代码
using system; using system.data; using system.configuration; using system.web; using system.web.security; using system.web.ui; using system.web.ui.webcontrols; using system.web.ui.webcontrols.webparts; using system.web.ui.htmlcontrols; using system.reflection; namespace dotnet.common.webform { using dotnet.common.model; using dotnet.common.util; public class basepage : system.web.ui.page { public basepage() { } protected override void oninit(eventargs e) { base.oninit(e); //cancelformcontrolenterkey(this.page.form.controls); //取消页面文本框的enter key } #region 取消页面文本控件的enter key功能 /// <summary> /// 在这里我们给form中的服务器控件添加客户端onkeydown脚步事件,防止服务器控件按下enter键直接回发 /// </summary> /// <param name="controls"></param> public virtual void cancelformcontrolenterkey(controlcollection controls) { //向页面注册脚本 用来取消input的enter key功能 registerundoenterkeyscript(); foreach (control item in controls) { //服务器textbox if (item.gettype() == typeof(system.web.ui.webcontrols.textbox)) { webcontrol webcontrol = item as webcontrol; webcontrol.attributes.add("onkeydown", "return forbidinputkeydown(event)"); } //html控件 else if (item.gettype() == typeof(system.web.ui.htmlcontrols.htmlinputtext)) { htmlinputcontrol htmlcontrol = item as htmlinputcontrol; htmlcontrol.attributes.add("onkeydown", "return forbidinputkeydown(event)"); } //用户控件 else if (item is system.web.ui.usercontrol) { cancelformcontrolenterkey(item.controls); //递归调用 } } } /// <summary> /// 向页面注册forbidinputkeydown脚本 /// </summary> private void registerundoenterkeyscript() { string js = string.empty; system.text.stringbuilder sb = new system.text.stringbuilder(); sb.append("function forbidinputkeydown(ev) {"); sb.append(" if (typeof (ev) != \"undefined\") {"); sb.append(" if (ev.keycode || ev.which) {"); sb.append(" if (ev.keycode == 13 || ev.which == 13) { return false; }"); sb.append(" } } }"); js = sb.tostring(); if (!this.page.clientscript.isclientscriptblockregistered("forbidinput2keydown")) this.page.clientscript.registerclientscriptblock(typeof(page), "forbidinput2keydown", js, true); } #endregion #region 利用反射取/赋页面控件的值 /// <summary> /// 从页面中取控件值,并给对象赋值 /// </summary> /// <param name="datatype">要被赋值的对象类型</param> /// <returns></returns> public virtual baseobj getformdata(type datatype) { baseobj data = (baseobj)activator.createinstance(datatype);//实例化一个类 type pgtype = this.gettype(); //标识当前页面 bindingflags bf = bindingflags.public | bindingflags.static | bindingflags.instance | bindingflags.nonpublic;//反射标识 propertyinfo[] propinfos = data.gettype().getproperties();//取出所有公共属性 foreach (propertyinfo item in propinfos) { fieldinfo fipage = pgtype.getfield(item.name, bf);//从页面中取出满足某一个属性的字段 if (fipage != null) //页面的字段不为空,代表存在一个实例化的控件类 { object value = null; control pgcontrol = (control)fipage.getvalue(this); //根据属性,找到页面对应控件,这要求页面控件命名必须和对象的属性一一对应相同 //下面取值 type controltype = pgcontrol.gettype(); if (controltype == typeof(label)) { value = ((label)pgcontrol).text.trim(); } else if (controltype == typeof(textbox)) { value = ((textbox)pgcontrol).text.trim(); } else if (controltype == typeof(htmlinputtext)) { value = ((htmlinputtext)pgcontrol).value.trim(); } else if (controltype == typeof(hiddenfield)) { value = ((hiddenfield)pgcontrol).value.trim(); } else if (controltype == typeof(checkbox)) { value = (((checkbox)pgcontrol).checked);//复选框 } else if (controltype == typeof(dropdownlist))//下拉框 { value = ((dropdownlist)pgcontrol).selectedvalue; } else if (controltype == typeof(radiobuttonlist))//单选框列表 { value = ((radiobuttonlist)pgcontrol).selectedvalue; if (value != null) { if (value.tostring().toupper() != "true" && value.tostring().toupper() != "false") value = value.tostring() == "1" ? true : false; } } else if (controltype == typeof(image)) //图片 { value = ((image)pgcontrol).imageurl; } try { object realvalue = null; if (item.propertytype.equals(typeof(nullable<datetime>))) //泛型可空类型 { if (value != null) { if (string.isnullorempty(value.tostring())) { realvalue = null; } else { realvalue = datetime.parse(value.tostring()); } } } else if (item.propertytype.equals(typeof(nullable))) //可空类型 { realvalue = value; } else { try { realvalue = convert.changetype(value, item.propertytype); } catch { realvalue = null; } } item.setvalue(data, realvalue, null); } catch (formatexception fex) { dotnet.common.util.logger.writefilelog(fex.message, httpcontext.current.request.physicalapplicationpath + "logfile"); throw fex; } catch (exception ex) { dotnet.common.util.logger.writefilelog(ex.message, httpcontext.current.request.physicalapplicationpath + "logfile"); throw ex; } } } return data; } /// <summary> /// 通过对象的属性值,给页面控件赋值 /// </summary> /// <param name="data"></param> public virtual void setformdata(baseobj data) { type pgtype = this.gettype(); bindingflags bf = bindingflags.public | bindingflags.instance | bindingflags.nonpublic | bindingflags.static; propertyinfo[] propinfos = data.gettype().getproperties(); foreach (propertyinfo item in propinfos) { fieldinfo myfield = pgtype.getfield(item.name, bf); if (myfield != null) { control mycontrol = (control)myfield.getvalue(this); //根据属性名取到页面控件 object value = item.getvalue(data, null); //取对象的属性值 type proptype = item.propertytype; if (value != null) { type valuetype = value.gettype(); try { type controltype = mycontrol.gettype(); if (controltype == typeof(label)) { if (valuetype == typeof(datetime)) { ((label)mycontrol).text = (convert.todatetime(value)).toshortdatestring(); } else { ((label)mycontrol).text = value.tostring(); } } else if (controltype == typeof(textbox)) { if (valuetype == typeof(datetime)) { ((textbox)mycontrol).text = (convert.todatetime(value)).toshortdatestring(); } else { ((textbox)mycontrol).text = value.tostring(); } } else if (controltype == typeof(htmlinputtext)) { if (valuetype == typeof(datetime)) { ((htmlinputtext)mycontrol).value = (convert.todatetime(value)).toshortdatestring(); } else { ((htmlinputtext)mycontrol).value = value.tostring(); } } else if (controltype == typeof(hiddenfield)) { ((hiddenfield)mycontrol).value = value.tostring(); } else if (controltype == typeof(checkbox)) { if (valuetype == typeof(boolean)) //布尔型 { if (value.tostring().toupper() == "true") ((checkbox)mycontrol).checked = true; else ((checkbox)mycontrol).checked = false; } else if (valuetype == typeof(int32)) //整型 (正常情况下,1标识选择,0标识不选) { ((checkbox)mycontrol).checked = string.compare(value.tostring(), "1") == 0; } } else if (controltype == typeof(dropdownlist)) { try { ((dropdownlist)mycontrol).selectedvalue = value.tostring(); } catch { ((dropdownlist)mycontrol).selectedindex = -1; } } else if (controltype == typeof(radiobutton)) { if (valuetype == typeof(boolean)) //布尔型 { if (value.tostring().toupper() == "true") ((radiobutton)mycontrol).checked = true; else ((radiobutton)mycontrol).checked = false; } else if (valuetype == typeof(int32)) //整型 (正常情况下,1标识选择,0标识不选) { ((radiobutton)mycontrol).checked = string.compare(value.tostring(), "1") == 0; } } else if (controltype == typeof(radiobuttonlist)) { try { if (valuetype == typeof(boolean)) //布尔型 { if (value.tostring().toupper() == "true") ((radiobuttonlist)mycontrol).selectedvalue = "1"; else ((radiobuttonlist)mycontrol).selectedvalue = "0"; } else ((radiobuttonlist)mycontrol).selectedvalue = value.tostring(); } catch { ((radiobuttonlist)mycontrol).selectedindex = -1; } } else if (controltype == typeof(image)) { ((image)mycontrol).imageurl = value.tostring(); } } catch (formatexception fex) { dotnet.common.util.logger.writefilelog(fex.message, httpcontext.current.request.physicalapplicationpath + "logfile"); } catch (exception ex) { dotnet.common.util.logger.writefilelog(ex.message, httpcontext.current.request.physicalapplicationpath + "logfile"); } } } } } #endregion #region 日志处理 /// <summary> /// 出错处理:写日志,导航到公共出错页面 /// </summary> /// <param name="e"></param> protected override void onerror(eventargs e) { exception ex = this.server.getlasterror(); string error = this.dealexception(ex); dotnet.common.util.logger.writefilelog(error, httpcontext.current.request.physicalapplicationpath + "logfile"); if (ex.innerexception != null) { error = this.dealexception(ex); dotnet.common.util.logger.writefilelog(error, httpcontext.current.request.physicalapplicationpath + "logfile"); } this.server.clearerror(); this.response.redirect("/error.aspx"); } /// <summary> /// 处理异常,用来将主要异常信息写入文本日志 /// </summary> /// <param name="ex"></param> /// <returns></returns> private string dealexception(exception ex) { this.application["stacktrace"] = ex.stacktrace; this.application["messageerror"] = ex.message; this.application["sourceerror"] = ex.source; this.application["targetsite"] = ex.targetsite.tostring(); string error = string.format("url:{0}\n引发异常的方法:{1}\n错误信息:{2}\n错误堆栈:{3}\n", this.request.rawurl, ex.targetsite, ex.message, ex.stacktrace); return error; } #endregion } }
2、使用反射给控件赋值
根据id取一个员工(employee),employee类继承自baseobj类,根据这个客户对象给页面控件赋值:
using system; using system.collections.generic; using system.linq; using system.web; using system.web.ui; using system.web.ui.webcontrols; using system.text; using system.threading; namespace webtest { using dotnet.common.webform; using dotnet.common.model; using entcor.hrm.model; public partial class _default : basepage { protected void page_load(object sender, eventargs e) { if (!ispostback) { employee employee = new employee { id = 1, username = "jeff wong", address = "北京", isleave = false, realname = "测试用户", state = "2" }; this.setformdata(employee); //给页面控件赋值 } } } }
3、使用反射给对象赋值
点击”测试”按钮,将页面控件(runat=server)的值赋给实体对象:
protected void btnset_click(object sender, eventargs e) { employee employee = (employee)this.getformdata(typeof(employee)); stringbuilder sb = new stringbuilder(); sb.append("登录名:" + employee.username + "<br/>"); sb.append("真实姓名:" + employee.realname + "<br/>"); sb.append("所在地:" + employee.address + "<br/>"); sb.append("是否离职:" + employee.isleave + "<br/>"); sb.append("在职状态:" + employee.state + "<br/>"); this.ltrcontext.text = sb.tostring(); }
总结:
(1)、对于页面中控件较多的情况,这个类里的反射取值和赋值的方法还是很有用的(比较恶心的是你要哼唧哼唧地对照实体类给页面控件命名。kao,实体类有代码生成器自动生成我就忍了,页面控件还要一一对应地命名,估计很多程序员在这方面没少花时间,还有就是不考虑反射对性能的影响)。不过从代码的简洁程度来看,这个确实显得out了;不过呢,笔者习惯了,命名多就多一些吧,在找到稳定可靠的解决方案之前,短时间看来是不会选择改进的了;
(2)、如果页面中有用户控件(usercontrol),用户控件里的子控件直接在页面中就比较难取到了(你可能已经看出问题的端倪来了),解决的方法就是在用户控件里生成实体类(这个可以模仿basepage写一个basecontrol类,让用户控件继承basecontrol,然后取值。本来想另开一篇介绍一下的,可是发现实现代码雷同,放弃);
(3)、取消页面文本框的enter key您可以参考《asp.net实现取消页面表单内文本输入框enter响应的方法》;
(4)、异常处理见(二)。
二、异常处理
1、日志类(自己写的一个简单通用的文本日志处理类)
using system; using system.collections.generic; using system.linq; using system.text; using system.io; using system.web; namespace dotnet.common.webform { /// <summary> /// 日志类(常用的都是log4net,这里简陋地实现一个写入文本日志类) /// </summary> public static class logutil { /// <summary> /// 写入异常日志 /// </summary> /// <param name="ex"></param> public static void writefilelog(string exmsg) { string path = httpcontext.current.request.physicalapplicationpath + "logfile"; filestream fs = null; streamwriter m_streamwriter = null; try { if (!directory.exists(path)) { directory.createdirectory(path); } path = path + "\\" + datetime.now.tostring("yyyymmdd") + ".txt"; fs = new filestream(path, filemode.openorcreate, fileaccess.write); m_streamwriter = new streamwriter(fs); m_streamwriter.basestream.seek(0, seekorigin.end); m_streamwriter.writeline(datetime.now.tostring() + "\n"); m_streamwriter.writeline("-----------------------------------------------------------"); m_streamwriter.writeline("-----------------------------------------------------------"); m_streamwriter.writeline(exmsg); m_streamwriter.writeline("-----------------------------------------------------------"); m_streamwriter.writeline("-----------------------------------------------------------"); m_streamwriter.flush(); } finally { if (m_streamwriter != null) { m_streamwriter.close(); } if (fs != null) { fs.close(); } } } } }
2、error.aspx
这个比较无语。通常用来提供一个有好的出错页面。对于开发人员,建议显示完整的异常信息。
下面贴一个对开发人员有帮助的页面:
(1)、设计页面
<%@ page language="c#" autoeventwireup="true" codebehind="error.aspx.cs" inherits="error" %> <!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>出错啦</title> </head> <body> <form id="form1" runat="server"> <div> <table width='100%' align='center' style='font-size: 10pt; font-family: trebuchet ms, arial'> <tr align='center'> <td align="center" colspan="2"> <b>error on page</b> </td> </tr> <tr> <td align='right' width="200"> <b>stacktrace :</b> </td> <td align='left'> <asp:label id="lblstacktrace" runat="server"></asp:label> </td> </tr> <tr> <td align='right'> <b>error message :</b> </td> <td align='left'> <asp:label id="lblmessageerror" runat="server"></asp:label> </td> </tr> <tr> <td align='right'> <b>source :</b> </td> <td align='left'> <asp:label id="lblsourceerror" runat="server"></asp:label> </td> </tr> <tr> <td align='right'> <b>targetsite :</b> </td> <td align='left'> <asp:label id="lbltagetsiteerror" runat="server"></asp:label> </td> </tr> </table> </div> </form> </body> </html>
(2)、实现代码
using system; using system.collections.generic; using system.linq; using system.web; using system.web.ui; using system.web.ui.webcontrols; public partial class errorpage : system.web.ui.page { protected void page_load(object sender, eventargs e) { this.lblstacktrace.text = this.application["stacktrace"] as string; this.lblmessageerror.text = this.application["messageerror"] as string; this.lblsourceerror.text = this.application["sourceerror"] as string; this.lbltagetsiteerror.text = this.application["targetsite"] as string; } }
完整实例代码代码点击此处本站下载。
希望本文所述对大家asp.net程序设计有所帮助。