asp.net实现非常实用的自定义页面基类(附源码)
本文实例讲述了asp.net实现非常实用的自定义页面基类。分享给大家供大家参考,具体如下:
看到前面几篇文章(如:《asp.net实现利用反射,泛型,静态方法快速获取表单值到Model的方法》)想到的。下面总结发布一个笔者在开发中常用的一个自定义BasePage类,废话不多说了,直接贴代码。
一、BasePage类
1、代码
usingSystem;
usingSystem.Data;
usingSystem.Configuration;
usingSystem.Web;
usingSystem.Web.Security;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.WebControls.WebParts;
usingSystem.Web.UI.HtmlControls;
usingSystem.Reflection;
namespaceDotNet.Common.WebForm
{
usingDotNet.Common.Model;
usingDotNet.Common.Util;
publicclassBasePage:System.Web.UI.Page
{
publicBasePage()
{
}
protectedoverridevoidOnInit(EventArgse)
{
base.OnInit(e);
//CancelFormControlEnterKey(this.Page.Form.Controls);//取消页面文本框的enterkey
}
#region取消页面文本控件的enterkey功能
///<summary>
///在这里我们给Form中的服务器控件添加客户端onkeydown脚步事件,防止服务器控件按下enter键直接回发
///</summary>
///<paramname="controls"></param>
publicvirtualvoidCancelFormControlEnterKey(ControlCollectioncontrols)
{
//向页面注册脚本用来取消input的enterkey功能
RegisterUndoEnterKeyScript();
foreach(Controlitemincontrols)
{
//服务器TextBox
if(item.GetType()==typeof(System.Web.UI.WebControls.TextBox))
{
WebControlwebControl=itemasWebControl;
webControl.Attributes.Add("onkeydown","returnforbidInputKeyDown(event)");
}
//html控件
elseif(item.GetType()==typeof(System.Web.UI.HtmlControls.HtmlInputText))
{
HtmlInputControlhtmlControl=itemasHtmlInputControl;
htmlControl.Attributes.Add("onkeydown","returnforbidInputKeyDown(event)");
}
//用户控件
elseif(itemisSystem.Web.UI.UserControl)
{
CancelFormControlEnterKey(item.Controls);//递归调用
}
}
}
///<summary>
///向页面注册forbidInputKeyDown脚本
///</summary>
privatevoidRegisterUndoEnterKeyScript()
{
stringjs=string.Empty;
System.Text.StringBuildersb=newSystem.Text.StringBuilder();
sb.Append("functionforbidInputKeyDown(ev){");
sb.Append("if(typeof(ev)!=\"undefined\"){");
sb.Append("if(ev.keyCode||ev.which){");
sb.Append("if(ev.keyCode==13||ev.which==13){returnfalse;}");
sb.Append("}}}");
js=sb.ToString();
if(!this.Page.ClientScript.IsClientScriptBlockRegistered("forbidInput2KeyDown"))
this.Page.ClientScript.RegisterClientScriptBlock(typeof(Page),"forbidInput2KeyDown",js,true);
}
#endregion
#region利用反射取/赋页面控件的值
///<summary>
///从页面中取控件值,并给对象赋值
///</summary>
///<paramname="dataType">要被赋值的对象类型</param>
///<returns></returns>
publicvirtualBaseObjGetFormData(TypedataType)
{
BaseObjdata=(BaseObj)Activator.CreateInstance(dataType);//实例化一个类
TypepgType=this.GetType();//标识当前页面
BindingFlagsbf=BindingFlags.Public|BindingFlags.Static|BindingFlags.Instance|BindingFlags.NonPublic;//反射标识
PropertyInfo[]propInfos=data.GetType().GetProperties();//取出所有公共属性
foreach(PropertyInfoiteminpropInfos)
{
FieldInfofiPage=pgType.GetField(item.Name,bf);//从页面中取出满足某一个属性的字段
if(fiPage!=null)//页面的字段不为空,代表存在一个实例化的控件类
{
objectvalue=null;
ControlpgControl=(Control)fiPage.GetValue(this);//根据属性,找到页面对应控件,这要求页面控件命名必须和对象的属性一一对应相同
//下面取值
TypecontrolType=pgControl.GetType();
if(controlType==typeof(Label))
{
value=((Label)pgControl).Text.Trim();
}
elseif(controlType==typeof(TextBox))
{
value=((TextBox)pgControl).Text.Trim();
}
elseif(controlType==typeof(HtmlInputText))
{
value=((HtmlInputText)pgControl).Value.Trim();
}
elseif(controlType==typeof(HiddenField))
{
value=((HiddenField)pgControl).Value.Trim();
}
elseif(controlType==typeof(CheckBox))
{
value=(((CheckBox)pgControl).Checked);//复选框
}
elseif(controlType==typeof(DropDownList))//下拉框
{
value=((DropDownList)pgControl).SelectedValue;
}
elseif(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;
}
}
elseif(controlType==typeof(Image))//图片
{
value=((Image)pgControl).ImageUrl;
}
try
{
objectrealValue=null;
if(item.PropertyType.Equals(typeof(Nullable<DateTime>)))//泛型可空类型
{
if(value!=null)
{
if(string.IsNullOrEmpty(value.ToString()))
{
realValue=null;
}
else
{
realValue=DateTime.Parse(value.ToString());
}
}
}
elseif(item.PropertyType.Equals(typeof(Nullable)))//可空类型
{
realValue=value;
}
else
{
try
{
realValue=Convert.ChangeType(value,item.PropertyType);
}
catch
{
realValue=null;
}
}
item.SetValue(data,realValue,null);
}
catch(FormatExceptionfex)
{
DotNet.Common.Util.Logger.WriteFileLog(fex.Message,HttpContext.Current.Request.PhysicalApplicationPath+"LogFile");
throwfex;
}
catch(Exceptionex)
{
DotNet.Common.Util.Logger.WriteFileLog(ex.Message,HttpContext.Current.Request.PhysicalApplicationPath+"LogFile");
throwex;
}
}
}
returndata;
}
///<summary>
///通过对象的属性值,给页面控件赋值
///</summary>
///<paramname="data"></param>
publicvirtualvoidSetFormData(BaseObjdata)
{
TypepgType=this.GetType();
BindingFlagsbf=BindingFlags.Public|BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Static;
PropertyInfo[]propInfos=data.GetType().GetProperties();
foreach(PropertyInfoiteminpropInfos)
{
FieldInfomyField=pgType.GetField(item.Name,bf);
if(myField!=null)
{
ControlmyControl=(Control)myField.GetValue(this);//根据属性名取到页面控件
objectvalue=item.GetValue(data,null);//取对象的属性值
TypepropType=item.PropertyType;
if(value!=null)
{
TypevalueType=value.GetType();
try
{
TypecontrolType=myControl.GetType();
if(controlType==typeof(Label))
{
if(valueType==typeof(DateTime))
{
((Label)myControl).Text=(Convert.ToDateTime(value)).ToShortDateString();
}
else
{
((Label)myControl).Text=value.ToString();
}
}
elseif(controlType==typeof(TextBox))
{
if(valueType==typeof(DateTime))
{
((TextBox)myControl).Text=(Convert.ToDateTime(value)).ToShortDateString();
}
else
{
((TextBox)myControl).Text=value.ToString();
}
}
elseif(controlType==typeof(HtmlInputText))
{
if(valueType==typeof(DateTime))
{
((HtmlInputText)myControl).Value=(Convert.ToDateTime(value)).ToShortDateString();
}
else
{
((HtmlInputText)myControl).Value=value.ToString();
}
}
elseif(controlType==typeof(HiddenField))
{
((HiddenField)myControl).Value=value.ToString();
}
elseif(controlType==typeof(CheckBox))
{
if(valueType==typeof(Boolean))//布尔型
{
if(value.ToString().ToUpper()=="TRUE")
((CheckBox)myControl).Checked=true;
else
((CheckBox)myControl).Checked=false;
}
elseif(valueType==typeof(Int32))//整型(正常情况下,1标识选择,0标识不选)
{
((CheckBox)myControl).Checked=string.Compare(value.ToString(),"1")==0;
}
}
elseif(controlType==typeof(DropDownList))
{
try
{
((DropDownList)myControl).SelectedValue=value.ToString();
}
catch
{
((DropDownList)myControl).SelectedIndex=-1;
}
}
elseif(controlType==typeof(RadioButton))
{
if(valueType==typeof(Boolean))//布尔型
{
if(value.ToString().ToUpper()=="TRUE")
((RadioButton)myControl).Checked=true;
else
((RadioButton)myControl).Checked=false;
}
elseif(valueType==typeof(Int32))//整型(正常情况下,1标识选择,0标识不选)
{
((RadioButton)myControl).Checked=string.Compare(value.ToString(),"1")==0;
}
}
elseif(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;
}
}
elseif(controlType==typeof(Image))
{
((Image)myControl).ImageUrl=value.ToString();
}
}
catch(FormatExceptionfex)
{
DotNet.Common.Util.Logger.WriteFileLog(fex.Message,HttpContext.Current.Request.PhysicalApplicationPath+"LogFile");
}
catch(Exceptionex)
{
DotNet.Common.Util.Logger.WriteFileLog(ex.Message,HttpContext.Current.Request.PhysicalApplicationPath+"LogFile");
}
}
}
}
}
#endregion
#region日志处理
///<summary>
///出错处理:写日志,导航到公共出错页面
///</summary>
///<paramname="e"></param>
protectedoverridevoidOnError(EventArgse)
{
Exceptionex=this.Server.GetLastError();
stringerror=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>
///<paramname="ex"></param>
///<returns></returns>
privatestringDealException(Exceptionex)
{
this.Application["StackTrace"]=ex.StackTrace;
this.Application["MessageError"]=ex.Message;
this.Application["SourceError"]=ex.Source;
this.Application["TargetSite"]=ex.TargetSite.ToString();
stringerror=string.Format("URl:{0}\n引发异常的方法:{1}\n错误信息:{2}\n错误堆栈:{3}\n",
this.Request.RawUrl,ex.TargetSite,ex.Message,ex.StackTrace);
returnerror;
}
#endregion
}
}
2、使用反射给控件赋值
根据id取一个员工(Employee),Employee类继承自BaseObj类,根据这个客户对象给页面控件赋值:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Text;
usingSystem.Threading;
namespaceWebTest
{
usingDotNet.Common.WebForm;
usingDotNet.Common.Model;
usingEntCor.Hrm.Model;
publicpartialclass_Default:BasePage
{
protectedvoidPage_Load(objectsender,EventArgse)
{
if(!IsPostBack)
{
Employeeemployee=newEmployee{ID=1,UserName="jeffwong",Address="北京",IsLeave=false,RealName="测试用户",State="2"};
this.SetFormData(employee);//给页面控件赋值
}
}
}
}
3、使用反射给对象赋值
点击”测试”按钮,将页面控件(runat=server)的值赋给实体对象:
protectedvoidbtnSet_Click(objectsender,EventArgse)
{
Employeeemployee=(Employee)this.GetFormData(typeof(Employee));
StringBuildersb=newStringBuilder();
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)、取消页面文本框的enterkey您可以参考《asp.net实现取消页面表单内文本输入框Enter响应的方法》;
(4)、异常处理见(二)。
二、异常处理
1、日志类(自己写的一个简单通用的文本日志处理类)
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.IO;
usingSystem.Web;
namespaceDotNet.Common.WebForm
{
///<summary>
///日志类(常用的都是log4net,这里简陋地实现一个写入文本日志类)
///</summary>
publicstaticclassLogUtil
{
///<summary>
///写入异常日志
///</summary>
///<paramname="ex"></param>
publicstaticvoidWriteFileLog(stringexMsg)
{
stringpath=HttpContext.Current.Request.PhysicalApplicationPath+"LogFile";
FileStreamfs=null;
StreamWriterm_streamWriter=null;
try
{
if(!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
path=path+"\\"+DateTime.Now.ToString("yyyyMMdd")+".txt";
fs=newFileStream(path,FileMode.OpenOrCreate,FileAccess.Write);
m_streamWriter=newStreamWriter(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)、设计页面
<%@PageLanguage="C#"AutoEventWireup="true"CodeBehind="Error.aspx.cs"Inherits="Error"%> <!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <htmlxmlns="http://www.w3.org/1999/xhtml"> <headrunat="server"> <title>出错啦</title> </head> <body> <formid="form1"runat="server"> <div> <tablewidth='100%'align='center'style='font-size:10pt;font-family:TrebuchetMS,Arial'> <tralign='center'> <tdalign="center"colspan="2"> <b>Erroronpage</b> </td> </tr> <tr> <tdalign='right'width="200"> <b>stackTrace:</b> </td> <tdalign='left'> <asp:LabelID="lblStackTrace"runat="server"></asp:Label> </td> </tr> <tr> <tdalign='right'> <b>Errormessage:</b> </td> <tdalign='left'> <asp:LabelID="lblMessageError"runat="server"></asp:Label> </td> </tr> <tr> <tdalign='right'> <b>Source:</b> </td> <tdalign='left'> <asp:LabelID="lblSourceError"runat="server"></asp:Label> </td> </tr> <tr> <tdalign='right'> <b>TargetSite:</b> </td> <tdalign='left'> <asp:LabelID="lblTagetSiteError"runat="server"></asp:Label> </td> </tr> </table> </div> </form> </body> </html>
(2)、实现代码
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
publicpartialclassErrorPage:System.Web.UI.Page
{
protectedvoidPage_Load(objectsender,EventArgse)
{
this.lblStackTrace.Text=this.Application["StackTrace"]asstring;
this.lblMessageError.Text=this.Application["MessageError"]asstring;
this.lblSourceError.Text=this.Application["SourceError"]asstring;
this.lblTagetSiteError.Text=this.Application["TargetSite"]asstring;
}
}
完整实例代码代码点击此处本站下载。
希望本文所述对大家asp.net程序设计有所帮助。