ASP.NET頁面間的傳值的幾種方法

 ASP.NET頁面間的傳值的幾種方法 
 ASP.NET WEB FORMS 給開發者提供了極好的事件驅動開發模式。然而這種簡單的應用程序開發模式卻給我們帶來了一些小問題,舉個例子,在傳統的ASP應用程序中,你能夠通過POST方法很容易的把一個值或多個值從一個頁面傳送到另一個頁面,用同樣的方法在ASP.NET中實現有點麻煩。在這裡,我們可以通過其他方式來解決這種情形。ASP.NET為我們提供了三種方式,一種是可以通過用QueryString來傳送相應的值,再一種是通過session變量來傳送相應的值,還有就是通過Server.Transfer方法來實現。下面分別一一介紹: 

一、使用Querystring
Querystring是一種非常簡單的傳值方式,其缺點就是會把要傳送的值顯示在瀏覽器的地址欄中,並且在此方法中不能夠傳遞對象。如果你想傳遞一個安全性不是那麼太重要或者是一個簡單的數值時,用此方法最好不過了。下面通過一個小例子來完成傳值工作,步驟如下:
1、創建一個web form
2、在新建的web form中放置一個button1,在放置兩個TextBox1,TextBox2
3、為button按鈕創建click事件
代碼如下:
private void Button1_Click
(object sender, System.EventArgs e)
{
string url;
url=”webform2.aspx?name=” +
TextBox1.Text + “&email=” +
TextBox2.Text;
Response.Redirect(url);
}
4、新建一個目標頁面命名為webform2
5、在webform2中放置兩個Label1,Label2
在webform2的Page_Load中添加如下代碼:
private void Page_Load
(object sender, System.EventArgs e)
{
Label1.Text=Request.QueryString[“name”];
Label2.Text=Request.QueryString[“email”];
}
運行,即可看到傳遞後的結果了。
二、使用Session變量
使用Session變量傳值是一種最常見的方式了,此中方式不僅可以把值傳遞到下一個頁面,還可以交叉傳遞到多個頁面,直至把Session變量的值removed後,變量才會消失。舉個例子看看:
1、創建一個web form
2、在新建的web form中放置一個button1,在放置兩個TextBox1,TextBox2
3、為button按鈕創建click事件
代碼如下:
private void Button1_Click
(object sender, System.EventArgs e)
{
Session[“name”]=TextBox1.Text;
Session[“email”]=TextBox2.Text;
Response.Redirect(“webform2.aspx”);
}
4、新建一個目標頁面命名為webform2
5、在webform2中放置兩個Label1,Label2
在webform2的Page_Load中添加如下代碼:
private void Page_Load
(object sender, System.EventArgs e)
{
Label1.Text=Session[“name”].ToString();
Label2.Text=Session[“email”].ToString();
Session.Remove(“name”);
Session.Remove(“email”);
}
運行,即可看到傳遞後的結果了。
三、使用Server.Transfer
雖然這種方法有點複雜,但也不失為一種在頁面傳值的方式。
舉個例子看看:
1、創建一個web form
2、在新建的web form中放置一個button1,在放置兩個TextBox1,TextBox2
3、為button按鈕創建click事件
代碼如下:
private void Button1_Click
(object sender, System.EventArgs e)
{
Server.Transfer(“webform2.aspx”);
}
4、創建過程來返回TextBox1,TextBox2控件的值代碼如下:
public string Name
{
get
{
return TextBox1.Text;
}
}
public string EMail
{
get
{
return TextBox2.Text;
}
}
5、新建一個目標頁面命名為webform2
6、在webform2中放置兩個Label1,Label2
在webform2的Page_Load中添加如下代碼:
private void Page_Load
(object sender, System.EventArgs e)
{
//創建原始窗體的實例
WebForm1 wf1;
//獲得實例化的句柄
wf1=(WebForm1)Context.Handler;
Label1.Text=wf1.Name;
Label2.Text=wf1.EMail;
}
運行,即可看到傳遞後的結果了

[轉][.NET] QueryString 的那些事

來源 http://www.dotblogs.com.tw/marcus116/archive/2012/07/29/73690.aspx

前言

Querystring是ASP.NET狀態管理(ASP.NET State Management)機制中常用到的傳遞資料方式之一

相信每個ASP.NET開發人員對此都很熟悉,此篇文章是自己對於Querystring資訊,整理給日後的自己看

有些事過30歲後就不一樣了XD

概述

Querystring(查詢字串)是附加在網頁URL結尾的資訊。主要是在Url上傳遞資料

可能是一個搜尋字串、頁碼、某項特定的指標…或類似的東西

在網址結尾加上一個問號(?)開始,每一組參數都是用「&」區隔開來,是一種KEY / Value的組合。

image

舉例來說(參考上圖),在Yahoo首頁搜尋引擎輸入「Hello world」後,在按下搜尋按鈕

會導頁到查詢結果頁面,並將符合搜尋字串相關資料呈現出來。

運作原理是透過Querystring作為資料傳遞,當你按下搜尋按鈕時,會將你在首頁(A網頁)輸入的搜尋字串「Hello world」傳遞到查詢結果呈現頁面(B網頁)

使用方式

取得Querystrnig參數內容方式:

  • C#:使用起來相當方便,可以用Requert.Querystring或是Request.Url.Query取得對應的值(註一)
01 // 設定
02 Response.Redirect("Default.aspx?參數名稱=" + 參數值)
03 Server.Transfer("Default.aspx?參數名稱=" + 參數值)
04
05 // 取得
06 // 指定特定key
07 string q = Request.QueryString["參數名稱"];
08 Response.Write(q);
09
10 // 取得集合
11 NameValueCollection nvc = Request.QueryString;
12 foreach (string key in nvc.Keys)
13 {
14     Response.Write("{0} => {1}", key, nvc[key]);
15 }
  • Client端:可以用Javascript寫一長串判斷來達到目的,在此建議可以用jQuery外掛(Query String Object)處理比較方便偷懶
1 /*使用jQuery外掛:jQuery String Object*/
2 // 設定
3 var newUrl = $.query.set("參數名稱", 參數值).toString();    
4
5 // 取得
6 var str = $.query.get('參數名稱');

註一:使用Request.QueryString會改變編碼,為確保接收參數不受影響,可以使用Request.Url.Query取得尚未解碼的原始字串,在進行解碼。

URL編碼

在URL網路標準規範中有規定,URL網址只能用英文字母和數字[0-9a-zA-Z]、一些特殊符號及特定保留字,才可以不經過編碼直接用在URL(註二)這意謂URL中如果有中文字的話,就必須經過編碼後使用。(註三)

在程式開發時,瀏覽器如果要在Querystring中帶有中文字或是特殊字元資料時,可以透過以下進行編碼&解碼

  • .Net Framework:
1 // 使用Server.UrlEncode進行編碼
2 String myURL = "http://www.ABC.com/Search.aspx?q=" + Server.UrlEncode("你好嗎");
3 Response.Write("<a href=" + myURL + "> 你好嗎 </a>");
4
5 // 使用Server.UrlDecode進行解碼
6 String myDecodedString = Server.UrlDecode(URI);
7 Response.Write("Decoded:" + myDecodedString );
  • Javascript:
1 // URL編碼:encodeURI():以UTF-8輸出,在每個字前面加上%
2 url = url + "?q=" + encodeURI("你好嗎");
3
4 // URL解碼:decodeURI()
5 document.write(encodeURI(URI)

在網路規範中沒有規定具體的編碼方法,瀏覽器本身可以自行設定,導致URL編碼有點混亂,開發上必須要更加小心

有關URL編碼的細節,我推薦大家可以參考「关于URL编码」,這篇文章中有詳細的介紹(我看完才比較瞭解,遮臉 XD)

註二:RFC 1783:”…Only alphanumerics [0-9a-zA-Z], the special characters “$-_.+!*'(),” [not including the quotes – ed], and reserved characters used for their reserved purposes may be used unencoded within a URL.”

註三:在google輸入「你好嗎」三個字時,按下搜尋之後,搜尋結果頁面網址呈現的查詢字串會是UTF-8編碼後「%E4%BD%A0%E5%A5%BD%E5%97%8E」

安全性

Querystring在使用上很方便,但以安全性考量來說,是有淺在安全性風險滴

因為可透過瀏覽器看到網址內容,清楚可見查詢的資訊,且使用者可任意修改

使用時有幾點建議(網路是很危險滴,大人們請多多留意阿)

  • 驗證資料:不要輕易相信從Client傳來的URL網址,對於Querystring的參數值是要經過驗證。有心的駭客要竊取網站資料,會將攻擊指令組成一長字串Querystring,進行SQL Inject攻擊(註四)
  • 敏感性資料:因為淺而易見,不要放置敏感性資料在Querystring
  • 長度限制:一些瀏覽器對於Querystring有長度限制,超過預設長度字元時,Querystring會被截斷,詳細可以參考ASP.NET 4.0 設定QueryString的最大長度

註四:SQL Inject可以參考黑暗大文章寫的游擊式的SQL Injection攻擊

[轉][SQL Server]幾種分頁(Paging)寫法

來源 http://www.dotblogs.com.tw/jimmyyu/archive/2009/11/09/11499.aspx

以下介紹幾種在SQL Server上簡單的分頁做法,大致分為三種:

1.Order By搭配not in

2.Temp Table

3.ROW_NUMBER() function

以下以Northwind資料庫作為範例:

Order By搭配not in

1 Select Top 10 CustomerID, CompanyName ,ContactName, Country from Customers where CustomerID Not in
2 (Select top 10 CustomerID from Customers order by CustomerID)
3 Order by CustomerID

此做法是透過Where條件中的not in排除掉前十筆資料,以下是前20筆資料:

 image

not in會幫忙排除掉CustomerID為1-10筆的內容,因此我們可以Select到11-20筆的資料結果:

image

Temp Table

1 select   identity(int,1,1) RowNum, CustomerID, CompanyName, ContactName, Country  into TempTable from Customers

將Select出來的欄位資料放到另一個Temp Table中,該Temp Table的第一個欄位是identity,為自動遞增的欄位,接著我們可對該Temp Table的RowNum(identity欄位)進行條件過濾;

1 Select from Temp where RowNum >= 11 AND RowNum <= 20

由於第一個欄位是自動遞增,我們就可以將它當成是我們所要的RowNum來進行查詢,得到的資料如下:

image

ROW_NUMBER() Function

這個功能是在SQL Server 2005後的版本才有提供的,我們可透過以下的語法來進行處理:

1 SELECT  *
2 FROM (SELECT  ROW_NUMBER() OVER (ORDER BY CustomerID)
3 AS RowNum, CustomerID, CompanyName, ContactName, Country FROM Customers)
4 AS NewTable
5 WHERE RowNum >= 11 AND RowNum <= 20

Select 出來的資料如下:

image

在管理便利性上,我個人比較不傾向選擇Temp Table的方式,1.3兩種做法是我比較會去使用的,而如果可以選擇的話我應該會以ROW_NUMBER()這個Function的解法優先,我們以這兩句SQL的執行計畫中來看就可以看出使用ROW_NUMBER()的執行成本是較低的,主要差異應在於ROW_NUMBER()只做了一次的Clustered Index Scan,而另一個方法則是兩次:

image

C# 字串變數, 如何包含雙引號或反斜線

如果字串裡包括特殊符號,例如換行符號,雙引號等,可以用\,例如\” 表示雙引號
以下是其他的範例
string a="abc\"dd"; //以 \" 表示雙引號
string b= "C:\\Program Files\\";  //以 \\ 表示反斜線
若在字串前加@,會比較方便撰寫,範例如下
string d = @"C:\Program Files\"; //加了@, 只需要寫一個反斜線即可,會比較簡單
string e = @"""C:\Program Files\"""; //加了@, 用"" 二個雙引號來表示一個雙引號

SqlDataReader

SqlDataReader一次只能讀取一行

實際用法為

//建立SQL命令對象
SqlCommand myCommand = new SqlCommand(strSQL, dbConn);
//得到Data結果集
SqlDataReader myDataReader = myCommand.ExecuteReader();

 

while (myDataReader.Read())
{

string i = myDataReader.GetName(0); //string 顯示欄位名稱 0為 第一欄 1為第二欄 以此類推

object j = myDataReader.GetValue(0); //object 顯示內容值 0為第一欄位內容 1為第二欄位內容 以此類推

}

DataTable.NewRow 方法

MSDN上的範例
注意 column也要加入,這樣 Datasource才會找到對應的欄位名稱

下列範例會使用 NewRow 方法來建立 DataTable、加入判斷資料表結構描述的兩個 DataColumn 物件,並建立多個新的 DataRow 物件。 然後,DataRow 物件是使用 Add 方法來加入至 DataRowCollection

private void MakeDataTableAndDisplay()
{
    // Create new DataTable and DataSource objects.
    DataTable table = new DataTable();

    // Declare DataColumn and DataRow variables.
    DataColumn column;
    DataRow row; 
    DataView view;

    // Create new DataColumn, set DataType, ColumnName and add to DataTable.    
    column = new DataColumn();
    column.DataType = System.Type.GetType("System.Int32");
    column.ColumnName = "id";
    table.Columns.Add(column);

    // Create second column.
    column = new DataColumn();
    column.DataType = Type.GetType("System.String");
    column.ColumnName = "item";
    table.Columns.Add(column);

    // Create new DataRow objects and add to DataTable.    
    for(int i = 0; i < 10; i++)
    {
        row = table.NewRow();
        row["id"] = i;
        row["item"] = "item " + i.ToString();
        table.Rows.Add(row);
    }

    // Create a DataView using the DataTable.
    view = new DataView(table);

    // Set a DataGrid control's DataSource to the DataView.
    dataGrid1.DataSource = view;
}

 

[轉][.NET]將DataTable轉成List物件

來源  http://www.dotblogs.com.tw/rainmaker/archive/2013/11/05/126727.aspx

今天看同事分享時,看到他們將DataTable轉成物件時,使用for…each的方式。

雖然有很多的ORM框架可以幫我們做到同樣的效果,但如果手動要做的話,有那些方式呢?

1 //要轉換的物件
2 public class Document
3 {
4     public string CompId { getset; }
5     public string HandleUnit { getset; }
6     public string No { getset; }
7 }

方法1:使用for…each (for…next也可以)

01 //將DataTable轉成List<物件>
02 DataTable dt = new DataTable();
03 dt.Columns.Add("CompId"typeof(string));
04 dt.Columns.Add("HandleUnit"typeof(string));
05 dt.Columns.Add("No"typeof(string));
06 dt.Rows.Add(new object[] {"655""EBS""001" });
07 dt.Rows.Add(new object[] { "655""ODM""002" });
08 dt.Rows.Add(new object[] { "655""OCS""003" });
09
10 //Way 1, for next
11 List<Document> Way1 = new List<Document>();
12 foreach (DataRow dr in dt.Rows)
13 {
14     Document doc = new Document();
15     doc.CompId = dr.Field<string>("CompId");
16     doc.HandleUnit = dr.Field<string>("HandleUnit");
17     doc.No = dr.Field<string>("No");
18     Way1.Add(doc);
19 }

方式2:建立Extension Methods透過Reflection來簡化(參考:fetch datarow to c# object)

01 public static class DataTableExtensions
02 {
03     public static IList<T> ToList<T>(this DataTable table) where T : new()
04     {
05         IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();
06         IList<T> result = new List<T>();
07
08         foreach (var row in table.Rows)
09         {
10             var item = CreateItemFromRow<T>((DataRow)row, properties);
11             result.Add(item);
12         }
13
14         return result;
15     }
16
17     public static IList<T> ToList<T>(this DataTable table, Dictionary<stringstring> mappings) where T : new()
18     {
19         IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();
20         IList<T> result = new List<T>();
21
22         foreach (var row in table.Rows)
23         {
24             var item = CreateItemFromRow<T>((DataRow)row, properties, mappings);
25             result.Add(item);
26         }
27
28         return result;
29     }
30
31     private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties) where T : new()
32     {
33         T item = new T();
34         foreach (var property in properties)
35         {
36             property.SetValue(item, row[property.Name], null);
37         }
38         return item;
39     }
40
41     private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties, Dictionary<stringstring> mappings) where T : new()
42     {
43         T item = new T();
44         foreach (var property in properties)
45         {
46             if (mappings.ContainsKey(property.Name))
47                 property.SetValue(item, row[mappings[property.Name]], null);
48         }
49         return item;
50     }
51 }

方式2.1:如果欄位名稱跟物件屬性名稱相同,則直接對應。

1 DataTable dt2 = new DataTable();
2 dt2.Columns.Add("CompId"typeof(string));
3 dt2.Columns.Add("HandleUnit"typeof(string));
4 dt2.Columns.Add("No"typeof(string));
5 dt2.Rows.Add(new object[] { "655""EBS""001" });
6 dt2.Rows.Add(new object[] { "655""ODM""002" });
7 dt2.Rows.Add(new object[] { "655""OCS""003" });
8 //Way 2, 如果欄位名稱跟屬性一樣,就直接Assign
9 var Wary2 = dt2.ToList<Document>();

方式2.2:如果欄位名稱跟物件屬性名稱不同,則建立Dictionary型態的Mapping物件,如下,

01 DataTable dt3 = new DataTable();
02 dt3.Columns.Add("CompId"typeof(string));
03 dt3.Columns.Add("HandleUnit"typeof(string));
04 dt3.Columns.Add("No"typeof(string));
05 dt3.Rows.Add(new object[] { "655""EBS""001" });
06 dt3.Rows.Add(new object[] { "655""ODM""002" });
07 dt3.Rows.Add(new object[] { "655""OCS""003" });
08 //Way 3, 如果欄位跟屬性不同,就建一個Mapping表
09
10 var mappings = new Dictionary<stringstring>();
11 mappings.Add("CompId""CompId");
12 mappings.Add("HandleUnit""HandleUnit");
13 mappings.Add("No""No");
14 var Way3 = dt3.ToList<Document>(mappings);

相信一定有一堆人會問說,為何要這樣做呢? 為何不使用ORM呢?  為什麼? 為什麼? …..等很多的疑問

同事回說,因為只是針對舊有的系統新增一個小的模組,而目前系統的Table有300多個,時間有限 … So…. 就先這樣搞…