欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-12-18 16:16:28
本文实例讲述了asp.net实现非常实用的自定义页面基类。分享给大家供大家参考,具体如下: 看到前面几篇文章(如:《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程序设计有所帮助。

上一篇:

下一篇: