当前位置: 移动技术网 > IT编程>开发语言>.net > asp.net实现非常实用的自定义页面基类(附源码)

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

2017年12月12日  | 移动技术网IT编程  | 我要评论

深圳会议桌,淄博晚报,唐山爆竹厂爆炸

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网