最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

asp.net实现非常实用的自定义页面基类(附源码)

来源:动视网 责编:小采 时间:2020-11-27 22:38:01
文档

asp.net实现非常实用的自定义页面基类(附源码)

asp.net实现非常实用的自定义页面基类(附源码):本文实例讲述了asp.net实现非常实用的自定义页面基类。分享给大家供大家参考,具体如下: 看到前面几篇文章(如:《asp.net实现利用反射,泛型,静态方法快速获取表单值到Model的方法》)想到的。下面总结发布一个笔者在开发中常用的一个自定义BasePag
推荐度:
导读asp.net实现非常实用的自定义页面基类(附源码):本文实例讲述了asp.net实现非常实用的自定义页面基类。分享给大家供大家参考,具体如下: 看到前面几篇文章(如:《asp.net实现利用反射,泛型,静态方法快速获取表单值到Model的方法》)想到的。下面总结发布一个笔者在开发中常用的一个自定义BasePag


本文实例讲述了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程序设计有所帮助。

文档

asp.net实现非常实用的自定义页面基类(附源码)

asp.net实现非常实用的自定义页面基类(附源码):本文实例讲述了asp.net实现非常实用的自定义页面基类。分享给大家供大家参考,具体如下: 看到前面几篇文章(如:《asp.net实现利用反射,泛型,静态方法快速获取表单值到Model的方法》)想到的。下面总结发布一个笔者在开发中常用的一个自定义BasePag
推荐度:
标签: 页面 ASP.NET 基类
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top