本文實例講述了asp.net實現非常實用的自定義頁面基類。分享給大家供大家參考,具體如下:
看到前面幾篇文章(如:《asp.net實現利用反射,泛型,靜態方法快速獲取表單值到Model的方法》)想到的。下面總結發布一個筆者在開發中常用的一個自定義BasePage類,廢話不多說了,直接貼代碼。
一、BasePage類
1、代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
|
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類,根據這個客戶對象給頁面控件賦值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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)的值賦給實體對象:
1
2
3
4
5
6
7
8
9
10
11
|
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、日志類(自己寫的一個簡單通用的文本日志處理類)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
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)、設計頁面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
<%@ 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" > <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)、實現代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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程序設計有所幫助。