ASP.NET頁面間的傳值的幾種方法
ASP.NET WEB FORMS 給開發者提供了極好的事件驅動開發模式。然而這種簡單的應用程序開發模式卻給我們帶來了一些小問題,舉個例子,在傳統的ASP應用程序中,你能夠通過POST方法很容易的把一個值或多個值從一個頁面傳送到另一個頁面,用同樣的方法在ASP.NET中實現有點麻煩。在這裡,我們可以通過其他方式來解決這種情形。ASP.NET為我們提供了三種方式,一種是可以通過用QueryString來傳送相應的值,再一種是通過session變量來傳送相應的值,還有就是通過Server.Transfer方法來實現。下面分別一一介紹:
月份: 2014 年 7 月
asp.net 按下按鈕後執行JavaScript
c#寫法
protected void btnNextPage_Click(object sender, EventArgs e)
{
Response.Write(“<script language=’javascript’>”);
Response.Write(“alert(‘新增成功!!’);”);
Response.Write(“location.href=’http://www.yahoo.com.tw’;”);
Response.Write(“</script>”);
Response.End();
}
asp.net 按下按鈕轉頁
protected void btnPrevPage_Click(object sender, EventArgs e)
{
Response.Redirect(“http://www.google.com”);
//btnPrevPage.PostBackUrl = “http://www.yahoo.com.tw”;
}
用
Response.Redirect(“http://www.google.com”); 按下按鈕後會轉至google
btnPrevPage.PostBackUrl = “http://www.yahoo.com.tw”; 這個還是連到自己的網頁
DropDownList加入Value和Text
DropDownList1.Items.Add(New ListItem(這裏是Text, 這裏是Value))
DropDownList1.Items.Add(new ListItem("11","台北市"));
[轉][.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的組合。
舉例來說(參考上圖),在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筆資料:
not in會幫忙排除掉CustomerID為1-10筆的內容,因此我們可以Select到11-20筆的資料結果:
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來進行查詢,得到的資料如下:
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 出來的資料如下:
在管理便利性上,我個人比較不傾向選擇Temp Table的方式,1.3兩種做法是我比較會去使用的,而如果可以選擇的話我應該會以ROW_NUMBER()這個Function的解法優先,我們以這兩句SQL的執行計畫中來看就可以看出使用ROW_NUMBER()的執行成本是較低的,主要差異應在於ROW_NUMBER()只做了一次的Clustered Index Scan,而另一個方法則是兩次:
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 方法
下列範例會使用 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 { get ; set ; } |
5 |
public string HandleUnit { get ; set ; } |
6 |
public string No { get ; set ; } |
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< string , string > 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< string , string > 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< string , string >(); |
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…. 就先這樣搞…