ASP.net 3.5 最佳實務講座(using Visual C#)
===================================================資料型別(佔用的位元組數)
bool(視執行環境而異)
byte(1byte) = 0-255
char,short(2)
int,float,object(4)
long,double(8)
decimal(16)
===================================================若宣告一個decimal變數,設常值時需加M或m,否則會被當成double處理
decimal price = 120M;
===================================================允許空值的變數
Nullable變數的宣告方式為在資料型別後面加一個?就可以。
int? age = null;
int? age = 25;
===================================================使用var關鍵字來取代指定型別宣告變數。
使用var宣告變數時一定要給初始值,否則C#並不會知道這個變數要給什麼型別。
var bookID = "ASP.NET";
var price = 500;
var isOnline = true;
===================================================常數宣告
const double pi = 3.14;
===================================================陣列宣告
int[] data = new int[3];
int[] data = {1,2,3};
string[,] data = new string[6,5];
Response.Write(data.Length); //30
Response.Write(data.GetLength(0)); //6
string[,,] data = new string[3,3,3];
Array.Copy(來源陣列名稱,目標陣列名稱,長度);
===================================================
is 比較運算子兩邊變數的型別是否相容
s is string
as 用來將變數轉換為相容型別
string s = someObject as string;
===================================================.ToUpper() 字串轉大寫
.ToLower() 字串轉小寫
.Trim() 去除前後空白
.TrimStart() 去除字串前面空白
.TrimEnd() 去除字串後面空白
.Length 取得字串長度
.ToString() 轉換為字串
.Substring(開始位置,取出長度) 取出部份字串
.IndexOf(字,開始位置) 判斷某個字出現的位置
.IndexOf(字,列舉單元)
s.IndexOf("a", StringComparison.CurrentCultureIgnoreCase);
.Replace(原始字串,取代為)
.Splite(new char[]{'字元'}) 一個字串可透過Splite()方法轉換為字串組的陣列
string EmpArray = "A,R,J,S";
string[] EmpArray = EmpNames.Splite(new char[]{','});
string.Join("字元",陣列)
string[] EmpNames = {"A","R","J","S"};
string Employee = string.Join(";",EmpNames);
string.Format(格式定義字串,...參數)
string.Format("{1}+{0}運算結果為:{2}",i , j , total);
{0}表示要放入之後的第一個變數
Request.UserHostAddress 取得網站伺服器IP位置
Request.FilePath 目前網頁的虛擬路徑
===================================================
DateTime.Now 傳回現在日期與時間
DateTime.Today 傳回現在日期與12:00
DateTime dt = new DateTime(2008,1,1,18,30,30);
DateTime.Now.DayOfWeek 今天星期幾(英文)
DateTime.Now.DayOfWeek.GetHashCode() 今天星期幾(數字)
Datetime dt;
DateTime.TryParse("欲判斷的日期",out dt) 判斷是否為日期時間
DateTime.Now.ToString("格式化字串")
若只使用一個格式字元,要在前面加上%
DateTime.Now.AddDays(-5)
Datetime dt = new DateTime(2008,10,24);
TimeSpan ts = dt.Subtract(DateTime.Now);
Response.Write(ts.Days.ToString());
===================================================
string s1 = "三百";
int currentValue = 0;
int.TryParse(s1, out currentValue) 判斷使否為數值
out 關鍵字會導致以傳址 (By Reference) 方式傳遞引數。
.ToString("數值格式")
decimal d = 12345.67M;
Response.Write(d.ToString("C1")); //取到小數點下第一位
===================================================
Convert類別專門負責型別轉換 Convert.ToXXXXXX
Convert.ToInt32 -> int
Convert.ToInt64 -> long
string dt = "2008年1月16日";
Convert.ToDateTime(dt).Day
Request.PhysicalApplicationPath 網頁所在實體路徑
===================================================
string.IsNullOrEmpty("字串")
switch運算式的結果必須為整數、列舉型態資料、字串(char)、或是字串(string)
default不一定要放在最後
foreach(型別 變數 in 集合或陣列名稱)
try
{}
catch(FormatException fex) //輸入字串格式不正確
{}
catch(OverflowException oex) //數值對Int32而言太大或太小
{}
catch(Exception ex)
{
變數 = ex.Message;
}
finally
{}
===================================================
App_Code目錄是用來存放程式碼的。所有外界對App_Code目錄的瀏覽要求,都會被ASP.NET擋下來,保護程式碼不被外界輕易的瀏覽到。
若只用類別名稱來識別,很容易就因為類別名稱重複而產生衝突,為解決這個問題,便在類別名稱前加上命名空間(Mamespace)。
通常命名空間會用公司名稱開頭,再依類別的功能分類。
public成員的名稱以大寫字母開頭
private成員的名稱則是以小寫開頭,且在前面加上底線以示區別
private DateTime _birthday;
public DateTime Birthday
{
//如果是唯讀的屬性,就不需要定義set存取子;而唯寫的屬性就不需要定義get存取子
get
{
//屬性被讀取或參考到實執行的程式
return _birthday;
}
set
{
//屬性被寫入或設定時執行的程式
//在set存取子中,內建有一個隱含變數value,可以用來接收外部程式傳到屬性上的資料
if (value < DateTime.Now)
{
_birthday = value;
}
else
{
_birthday = DateTime.MinValue;
}
}
}
自動實作屬性 - 不需要任何邏輯用來判斷或實作時使用
public string Name {get; set;}
public string Name {get; private set;} //Name屬性唯讀
所謂部分類別(partial class)就是將一個類別分割成多個檔案。
public pratial class Employee {} (in Employee_partial1.cs)
public pratial class Employee {} (in Employee_partial2.cs)
類別的完整名稱是:命名空間.類別名稱
匯入命名空間
<%@ Import Namespace="AjaxSoft.HR" %>
如果類別沒有定義命名空間,宣告時只要指定類別名稱即可。
在存取物件成員之前可先檢查一下,物件是否為null
if(物件 == null)
===================================================
<!DOOCTYPE> 幫助檢查網頁中的HTML標籤是否正確
ASP.NET規定一個網頁裡只能有一組<form runat="server">...</form>。而且<form>的runat屬性值一定要設為"server"。
ASP.NET常用的伺服器控制項以<asp:...>開頭,另外一定會有runat="server"的屬性,故稱為"伺服器"控制項。
使用者在此控制項輸入或選擇的內容會被傳回伺服器裡。
<asp:....> 都會有id以及runat="server"屬性
WebForm執行時,所有的伺服起控制項都會被轉換成標準的HTML標籤。
使用者在網頁中輸入的資料,在ASP.NET裡稱為"檢視狀態(view state)",ASP.NET的伺服器控制項會自動將這些資料以Base64編碼,放在網頁裡的隱藏欄位裡。
加了runat="server"屬性後會保留檢視狀態。
如果在一個網頁中所設定的CSS樣式表,將來可能會在其他的網頁中共用的話,那麼最好的方式就是將可能會共用的CSS樣式表全部集中在一個CSS樣式檔案,
然後在各個不同的網頁中使用,這樣的方式稱為"附加樣式表"。
ASP.NET的Web Form版面預設為流程配置(Flow Layout)。
===================================================
單一檔案的程式碼儲存方式 程式碼會放在<script runat="server">...</script>裡。
<%@Page...%>裡額外加入"CodeFile"屬性,主要是用來記錄此Web Form的程式碼式儲存在哪個程式中。Inherits則是紀錄類別名稱。
<%@ Page Language="C#" CodeFile="CodeSeparation.aspx.cs" Inherits="CodeSeparation" %>
在HTML中只要是包在<%...%>區段中可視為執行伺服器端的程式碼,與在<script runat="server">...</script>一樣。
在"原始檔"檢視中建立事件處理常式時,在原本的<asp:Button>標籤中會多了一項屬性"OnClick",這個屬性紀錄的就是當Click事件發生時相關的事件處理常式名稱。
所有的事件處理常式都會有兩個引數:第一個是sender代表觸發事件的來源物件,另一個是紀錄相關事件資訊的EventArgs物件變數e。
即使兩個按鈕的Click事件處理常式是同一個,還是可以用sender判斷事件觸發的原始物件。
protected void Button1_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
Response.Write(btn.ID + "觸發這段程式");
}
Web Form裡的事件可分成兩類:伺服器控制事件(如:Button1.Click, TextBox1.TextChanged等)及網頁事件(如:Page.Load,Page.Unload等)。
網頁事件是每一次瀏覽網頁時都"一定會"觸發的
預設每一次要求(使用HTTP POST方法),都會在伺服器上執行程式碼,然後動態產生標籤回到自己這個網頁,這個行為稱之為PostBack。
程式中可用Page.IsPostBack進行判斷,若是首次瀏覽本頁,Page.IsPostBack的值為False,
若是在同一頁按下按鈕,瀏覽器會將此頁的內容回傳(PostBack),這個時候,程式讀取Page.IsPostBack的結果就是True。
某些伺服器控制項提供"AutoPostBack"屬性,當此屬性設定為True時,一但伺服器控制項的內容有所變更,便會自動回傳,不需再額外按鈕。
Calendar控制項雖然沒有AutoPostBack屬性,但是它本身就有AUtoPostBack的效果,只要在月曆上做選取動作就會導致自動回傳。
網頁生命週期的順序:
A.使用者請求一個伺服器的網頁
B.伺服器便建立Page物件的實體
C.執行網頁中的程式碼
D.產生標籤送至瀏覽器
E.丟棄Page物件
===================================================
用Response.Write寫出字串,字會顯示在網頁的最上方,無法控制出現在特定位置。
.Text 顯示的文字
.ToolTip 當滑鼠游標移至此控制項時顯示的工具提示
.ImageUrl 屬性設定要顯示的圖檔位置
可用"~/"代表網案的根目錄
Image.AlternateText 當無法顯示影像時的替代文字
HyperLink.NavigateUrl 要瀏覽的URL
HyperLink.Target NavigateUrl的目標框架
TextBox.MaxLength 預設值為0表示不限制
TextBox.TextMode = SingleLine | MultiLine | Passowrd
TextBox.Wrap 自動折行
將使用者在TextBoxMulti輸入的文字,依照其原始的換行方式再顯示一次:
Label1.Text = TextBoxMulti.Text.Replace(Environment.NewLine,"<br/>");
[Button|LinkButton|ImageButton].OnClientClick 在用戶端OnClick上執行的用戶端指令碼(JavaScript)
<asp:Button ID="ButtonOpen" runat="server" Text="開新視窗" OnClientClick="Navigate();">
CheckBox.Checked 控制項的核取狀態
Calendar.SelectionMode =[Day|DayWeek|DayWeekMonth]
protected void Calendar1_SelectionChanged(object sender, EventArgs e)
{
for (int i = 0; i < Calendar1.SelectedDates.Count; i++)
{
//ToShortDateString() 簡短日期顯示,不出現時間
Response.Write(Calendar1.SelectedDates[i].ToShortDateString() + ",");
}
// 清除選取日期
Calendar1.SelectedDates.Clear();
}
protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)
{
DateTime dt = new DateTime(2008,1,30);
if(e.Day.Date == dt)
{
Label LabelBR = new Lable();
LabelBR.Text = "<br/>";
e.Cell.Controls.Add(LabelBR);
HyperLink link = new HyperLink();
link.Text = "ASP.NET研討會";
link.NavigateUrl = "http://www.asp.net";
e.Cell.Controls.Add(link);
}
}
var items = new ListItemCollection();
items.Add("ASP.NET網站開發學習講座");
items.Add(new ListItem("ASP.NET網站開發學習講座","A001"));
items.Insert(0, "ASP.NET");
items.Clear(); //清除集合中所有的項目
items.RemoveAt(0); //只移除某個位置的項目
foreach( ListItem item in items)
{
Response.Write(item.Text + "<br />");
}
BulletedList.BullerStyle 設定條列效果屬性
BulletedList1.Items.Add("http://www.asp.net");
ListItem.Text 顯示在網頁上的項目文字
ListItem.Value 內部使用文字
RadioButtonList.RepeatDirection 從上而下或從左而右顯示
RadioButtonList.RepeatColumns 決定每一列只能顯示幾個項目
RadioButtonList1.SelectedItem.Text
RadioButtonList1.SelectedValue
RadioButtonList1.SelectedIndex
foreach( ListItem item in CheckBoxList1.items)
{
if(item.Selected == true)
{
Response.Write(item.Text + "<br />");
}
}
ListBox.Height 顯示行數(第一優先)
ListBox.Rows 顯示行數
ListBox.SelectionMode 單選或多選
單選控制項.SelectedItem
單選控制項.SelectedItem.Text
單選控制項.SelectedValue
單選控制項.SelectedIndex
foreach( ListItem item in 多選控制項.items)
{
if(item.Selected == true)
{
Response.Write(item.Text + "<br />");
}
}
===================================================
所有驗證控制項都要設定ControlToValidate屬性,用它來指定驗證對象。
ErrorMessage屬性用來設定驗證失敗時的錯誤訊息。在預設情況下,錯誤訊息會出現在驗證控制項的位置上。因為驗證控制項的Display屬性為Static。
若你不希望錯誤訊息出現在固定的位置,可將驗證控制項的Display屬性改設為Dynamic,錯誤訊息會視情況動態調整出現的位置。
若要取消使用者端驗證,可將驗證控制項的EnableClientSideScript屬性設為False。
每個驗證控制項只能做一種檢查,若要對同一個欄位進行一項以上的檢查,你可以結合多個驗證控制項,並將他們的ControlToValidate都指向同一個控制項。
InitialValue屬性設定驗證條件的初始值
CompareValidor必須設定:
ControlToValidate
ValueToCompare
Type
Operator
與另一個控制項相比較
ControlToValidate:TextBoxConfirm("確認密碼"輸入欄位)
ControlToCompare:TextBoxPassword("密碼"輸入欄位)
RangeValidator必須設定:
ControlToValidate
MaximumValue
MinimumValue
Type
RegularExpressionValidator必須設定:
ControlToValidate
ValidationExpression
protected void CustomValidator1_ServerValidate(object source, ServerValidateEventArgs args)
{
var quantity = int.Parse(args.Value); //args.Value 使用者輸入的值
if(quantity % 3 == 0)
{
args.IsValid = true; //驗證成功
}
else
{
args.IsValid = false;
}
}
若要使用JavaScript的驗證條件,則要設定CustomValidator的CLientValidationFunction屬性,對應到所提供的JavaScript函式。
驗證控制項的Text屬性設為"*"後,錯誤訊息只會出現在ValidationSummary。
ValidationSummary.ShowMessageBox 使用彈出視窗
ValidationSummary.ShowSummary 網頁顯示錯誤訊息
ASP.NET驗證控制項的邏輯是:必須通過網頁中"每一個"驗證才算是合法的輸入。
ValidationGroup屬性可將驗證控制項分組。當一個群組的驗證都通過就算成功,不會做也不會理會另一個群組的驗證規則。
===================================================
ASP.NET提供一個可以將網頁內文和網頁架構分別設計的方式,這個方式稱為主版頁面(Master Page)。
由於主板頁面是用來定義共用的部份,至於每個網頁不同的內容部份,則利用ContentPlaceHolder來代表。
主板頁面是ASP.NET的一種檔案類型,副檔名為.master。
主板頁面第一行是@Master指示詞。
引用主板頁面的網頁稱為內容頁面(Content Page)。
網頁的共用部分交給主板頁面設計,而網頁的主要內容則交由內容頁面負責設計與呈現。
內容頁面是網頁應用程式(Web Form)的一種,其副檔名為.aspx。
內容頁面必須在@Page指示詞多設定一個MasterPageFile屬性,以指定所使用的主板頁面。
不能有<html>、<head>、<body>和執行在伺服器端的<form>標籤,因為這些標籤早已定義在主板頁面中。
為了對應到主板頁面的ContentPlaceHolder控制項,在內容頁面一定要加入Content控制項。
Content控制項的ContentPlaceHolderID一定要與主板頁面中ContentPlaceHolder控制項的ID屬性值對應,否則程式將會出錯。
你可以在PreInit階段以動態方式指定主板頁面
protected void Page_PreInit(object sender, EventArgs e){
this.MasterPageFile = "~/MasterPage.master";
}
要解決主板頁和內容頁面間,一般HTML控制項"相對路徑"的問題(檔案找不到),可以將這些HTML控制項設定為伺服器控制項,接著使用控制項伺服器的路徑設定方式。
在內容頁面內控制主板頁面,可以在內容頁面使用Page物件的Master屬性取得所引用的主板頁面。
this.Master.Page.Title = "ASP.NET 3.5 完全探索";
(<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" Title="ASP.NET 3.5 網站開發學習講座" %>)
在內容頁面內使用Master.FindControl()方法,就可以找到主板頁面的控制項。
protected void Page_Load(object sender, EventArgs e) {
Image img = (Image)this.Master.FindControl("Image控制項ID");
img.ImageUrl = "~/Images/userManager.jpg";
}
===================================================
App_Data是ASP.NET應用程式為儲存資料而設立的目錄,像是SQL資料庫的MDF檔案、XML檔案等,都應該且十分適合放在這個目錄下,因為ASP.NET會保護App_Data下的內容。
===================================================
在.Net中所有存取資料庫的動作都是透過ADO.NET。
ADO.NET資料存取模式:
連線模式 SqlConnection -> SqlCommand -> SqlDataReader
離線模式 SqlConnection -> SqlDataAdapter -> DataSet
對於網站App_Data目錄的實際位置可以|DataDirectory|關鍵字代表。
SqlConnection物件用ConnectionString屬性儲存連線字串。
在還沒有要執行SQL指令之前,可以先建立及設定SqlConnection物件,但不需要馬上開啟連線。
SqlCommand.Connection 屬性指定連線物件
SqlCommand.CommandText屬性指定SQL指定
SqlCommand.ExecuteNonQuery() 適用INSERT、UPDATE、DELETE指令
SqlCommand.ExecuteReader() 適用SELECT指令
SqlException.Number 在SQL Server的master系統資料庫中有一個叫做messages的檢視表。
呼叫SqlDataAdapter物件的Fill方法時,便會執行其中的SQL查詢指令,將取回的資料填入指定的DataSet物件的資料表中。
DataSet物件中的資料表名稱可以自訂,沒有規定要與原資料中的資料表名稱相同。
SqlCommand物件若有以@符號開頭的參數,都會被記錄在Parameters集合裡。
ASP.NET提供的伺服器控制項,有些可以與資料"繫結"在一起,只要將伺服器控制項的資料來源(Data Source)設定到某個SqlDataReader物件,就可以很方便地透過SqlDataReader物件讀取相關的資料。
----------------------------------------
連線模式範例:
<%@ Import Namespace = "System.Data.SqlClient" %>
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection cn = new SqlConnection();
cn.ConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|NORTHWND.MDF;Integrated Security=True;User Instance=True";
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandText = "INSERT Customers (CustomerID, CompanyName) VALUES('AAASP','ASPNET Company')";
// cmd.CommandText = "UPDATE Customers SET CompanyName='AjaxSoft' WHERE CustomerID='AAASP'";
// cmd.CommandText = "DELETE Customers WHERE CustomerID='AAASP'";
// cmd.CommandText = "Select * from Customers";
// 在SQLCommand中設定參數值
// cmd.CommandText = "Select ProductName from Products where CategoryID=@CategoryID";
// cmd.Parameters.AddWithValue("@CategoryID", TextBoxCategory.Text);
// SqlDataReader dr = null;
try
{
cn.Open();
int records = cmd.ExecuteNonQuery();
//dr = cmd.ExecuteReader();
//GridView1.DataSource = dr;
//GridView1.DataBind();
//if (dr.HasRows)
//{
// while (dr.Read())
// {
// Response.Write("客戶編號:" + dr["CustomerID"] + "<br/>");
// Response.Write("<li>" + dr["ProductName"] + "<br/>");
// }
//}
}
catch (SqlException sqlex)
{
Response.Write("資料庫例外:(" + sqlex.Number + ")" + sqlex.Message + "<br/>");
}
catch (Exception ex)
{
Response.Write("例外:" + ex.Message + "(" + ex.Source + ")<br/>");
Response.Write(ex.StackTrace + "<br/>");
}
finally
{
if (cn.State == System.Data.ConnectionState.Open)
{
cn.Close();
}
//if (!dr.IsClosed)
//{
// dr.Close();
//}
}
}
----------------------------------------
離線模式範例:
<%@ Import Namespace = "System.Data.SqlClient" %>
<%@ Import Namespace = "System.Data" %>
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection cn = new SqlConnection();
cn.ConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|NORTHWND.MDF;Integrated Security=True;User Instance=True";
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
// 在SQLCommand中設定參數值
cmd.CommandText = "Select ProductName from Products where CategoryID=@CategoryID";
cmd.Parameters.AddWithValue("@CategoryID", TextBoxCategory.Text);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
DataSet ds = new DataSet();
da.Fill(ds, "Products");
foreach (DataRow dr in ds.Tables["Products"].Rows)
{
Response.Write("<li>" + dr["ProductName"] + "<br/>");
}
cn.Close();
}
===================================================
將網站使用到的連線字串統一放在web.config應用程式組態檔中,不僅修改不會導致網站重新編譯,
而且更新時也只要變更一個地方,所有網頁連線建立時便會參考到最新的連線字串,管理上也便利多了。
透過SqlDataSource控制項的DataSurceMode屬性,可控制取回的資料要以DataSet還是DataReader傳回。
DataSet模式可支援較多的應用,像是分頁、排序、篩選等,也是新增SqlDataSource控制項時的預設模式。
GridView的分頁如何顯示由PagerSetting屬性決定。
分頁導覽列的樣式是由PagerStyle屬性決定。
預設GridView的排序是依遞增方式排序,如果不想用這種方式排序,便可在Sorting事件裡以程式變更。
sortExpression:排序運算式
sortDirection:排序方式
SortExpression排序運算是可以放入一個以上的資料行作為排序條件
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
if (e.SortExpression == "Ttile")
{
e.SortExpression = "Title,FirstName";
e.SortDirection = SortDirection.Descending;
}
else
{
e.SortDirection = SortDirection.Ascending;
}
}
如果想要將某一個欄位的排序功能取消,最快的方式就是將這個特定欄位的SortExpression暑性質清空。
HyperLinkField屬性
DataNavigateUrlFields:CustomerID,Country
DataNavigateUrlFormatString:GetOrders.aspx?CustomerID={0}&Country={1}
Eval函式用來取出目前這筆資料的某一個欄位,像是Eval(:"FirstName")。Eval每一次只能取出一個欄位的值。Eval的傳回值是個Object,必須先做型別轉換。
在設定資料來源時,設定Select陳述式時選擇"指定自訂SQL陳述式或預存程序",只要SelectCommand裡面含有@開頭的查詢參數,便可進入繫結查詢參數的畫面。
===================================================
SqlDataSource標籤裡包含三個指令:SelectCommand、UpdateCommand、DeleteCommand。
SelectCommand一定得將每筆資料的主索引建值取回,目的是為了讓GridView可以唯一識別每一筆資料,如此才能正確地更新、刪除使用者指定的資料。
若要產生一個可刪除的GridView,作為它資料來源的SqlDataSource必須包含SelectCommand及DeleteCommand。
若要產生一個可編輯的GridView,作為它資料來源的SqlDataSource必須包含SelectCommand及UpdateCommand。
為了讓GridView知道透過哪個主索引鍵唯一識別每一筆資料,你必須以GridView的DataKeyNames屬性設定。如此GridView私底下便會將每一筆資料的主索引鍵值放在DataKeys集合中。
當GridView自SqlDataSource取得要顯示的資料時,便會同時將主索引鍵填入DataKeys集合。
有些資料表的主索引鍵是由兩個欄位組成的,此時GridView的DataKeyNames屬性便需輸入兩個欄位名稱,欄位名稱之間用逗號分隔。
通常主索引鍵值在資料更新後就不允許改變,因此,GridView的"啟用刪除"或"啟用編輯"智慧標籤設定後,都會將GridView的主索引鍵欄位設定為唯讀的狀態。
RowDeleting事件參數e的屬性:
e.Keys:取得欲刪除那筆資料的主索引鍵值。
e.Values:取得欲刪除那筆資料,除了主索引鍵之外的欄位值。
e.RowIndex:目前要刪除這筆資料在GridView中的索引值。
若是GridView有啟用分頁,假設在每頁10筆的情況下,則第2頁的第一筆資料的RowIndex是0而非10。
RowDeleted事件參數e的屬性:
e.ExceptionHandled:若有例外發生且沒有設為true時,會直接在網頁上顯示例外的錯誤畫面。
RowUpdating事件參數e的屬性:
e.OldValues:取得欲更新那筆資料,除了主索引鍵值欄位之外的原始值。
e.NewValues:取得欲更新那筆資料,除了主索引鍵值欄位之外的更新值。
預設SqlDataSource會將空字串的參數值視為Null。若不希望如此,而是直接將空字串寫入資料庫中,可將位於<UpdateParameters>...<UpdateParameters>中的<asp:Parameter />加入ConvertEmptyStringToNull屬性,並將它的值設為false。
TemplateField包含以下幾種樣板:
ItemTemplate
AlternatingItemTemplate
EditItemTemplate:進入編輯模式時使用
HeaderTemplate
FooterTemplate
InsertTemplate:只有DetailsView資料繫結控制項才支援新增功能
Bind提供雙向繫結(讀取/寫回資料庫)功能,但Eval僅提供讀取功能。
新增或轉換既有的欄位成一個TemplateField,如此才能自訂編輯樣板。
===================================================
LINQ(Language Integrated Query)
"LINQ to SQL設計師"可將關連資料庫,轉成一個DataContext物件模型,以便在程式中用LINQ語法存取。
"LINQ to SQL設計師"會建立DataContext類別外,另外還會為資料表建立對應的類別,這些類別稱為"Entity類別"。
每個資料表會對應成一個"Entity類別",而資料表中的欄位就對應成"Entity類別"的屬性,資料表中的每筆資料就是"Entity類別"的實例。
每個Entity類別都是"部分類別(partial class)",換句話說,你可以很方便地加以擴充,根據需要加入額外的屬性及方法。
設定命名時Entity類別名稱會自動變成單數:
[工具]->[選項],展開[資料庫工具]下的[O/R設計工具],將[名稱的複數表示]的[啟用]設為True。
若屬性的名稱已經被類別搶先了,為了避免不必要的困擾,會自動將屬性更名。
若父子類別為一對多的關係,則會在父類別新增一個原本資料表中沒有的屬性。注意屬性名稱為複數,表示它是個內含多筆資料的集合。
當程式中使用到LINQ語法時,請引用System.Linq命名空間:
<@ Import Namespace = "System.Linq" @>
注意.NET命名慣例會使用複數形式為集合命名。
BulletedList1.DataSource = db.publishers;
BulletedList1.DataTextField = "pub_name"; //在資料來源中提供項目文字的欄位
BulletedList1.DataBind();
--------------------
PubsDataContext db = new PubsDataContext(); //建立DataContent物件,透過它連接到實體的資料庫
var result = from p in db.publishers
where p.state == null
orderby p.pub_id descending
select new
{
ID = p.pub_id,
Name = p.pub_name,
Country = p.country,
State = p.state
};
GridView1.DataSource = result.Skip(2).Take(2); //注意:執行會有先後順序
//GridView1.DataSource = result.Where(r=>r.State==null);
//GridView1.DataSource = result.Orderby(r=>r.Price);
GridView1.DataBind();
注意到LINQ不是在查詢語法中指定傳回筆數的,它是在讀取資料時用Take()指定。
LINQ有所謂的"延遲執行模式(deferred execution model)",即查詢其實並不會馬上執行,而是等到真的需要用到資料的時候才會執行。
你在程式中對資料的異動其實是先暫存在本機的記憶體中,一直要等到呼叫SubmitChanges()時才會將整批異動寫入資料庫,因此是批次更新,而非即時更新。
如果要新增多筆資料,而且已經放在一個集合裡,則可呼叫InsertAllOnSubmit(),加入集合中所有的資料。
PubsDataContext db = new PubsDataContext();
title tAA1111 = db.titles.Single(t => t.title_id == "AA1111");
publisher pFiveLakes = db.publishers.Single(p => p.pub_id == "1622");
pFiveLakes.titles.Add(tAA1111);
db.SubmitChanges();
若集合中有一筆以上的資料符合查詢條件,Single()會丟出例外。
若要更新的只有一筆資料,可用Single()取出一筆資料。
若要更新多筆資料,可用where條件進行篩選取出符合的資料後,再逐一修改即可。
在尚未呼叫SubmitChanges()前的資料異動都被保留在程式執行端的記憶體中,而非資料庫端,因此,
不會影響到資料庫端的效能,資料庫端也不用為LINQ to SQL安裝任何軟體或設定。
所有"LINQ to SQL設計師"產生的類別都是部分類別(partial class),所以若要在資料維護時加入檢查屬性的條件,
只要實做對應的OnXXXChanging()或OnXXXChanged()方法,便可以在新增、刪除、修改資料或欄位值之前或之後,觸發所需的檢查動作。
例如:若要在pubdate屬性被修改之前進行檢查,便可實做OnpubdateChanging()方法,將檢查條件寫在其中。
除了針對個別屬性驗證,有時候驗證條件是跨屬性的,可能得同時把數個屬性一併比較才會知道合不合理,
所幸LINQ to SQL提供物件層級的驗證機制,一樣也是在部分類別中實做部分方法,物件層級的驗證方法只有一個:OnValidate(),這個方法會在資料寫入資料庫前被呼叫。
OnValidate()中若發生任何例外,便會中止更新資料庫的作業。
在OnVlidate()方法被呼叫時會傳入一個System.Data.Linq.ChangeAction引數,你可以利用這個引數判斷目前的維護動作是新增、刪除還是修改。
public partial clas title
{
partial void OnpubdateChanging(DateTime value)
{
if(value > DateTime.Now)
{
throw new Exception("出版日期不可大於今天");
}
}
partial void OnValidate(System.Data.Linq.ChangeAction action)
{
if(action == System.Data.Linq.ChangeAction.Delete)
throw new NotImplementedException();
}
}
使用LinqDataSource控制項之前,必須先準備好DataContent類別。
===================================================
ASP.NET網站有兩種驗證類型:Forms及Windows。
<configuration>
<system.web>
<authentication mode="Forms">
<forms defaultUrl="Home.aspx" loginUrl="UserLogin.aspx" />
</authentication>
</system.web>
</configuration>
在沒有<forms>的情況下,登入後的預設網頁為Default.aspx,登入網頁為Login.aspx。
設定子目錄的存取規則
<configuration>
<location path="Member">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
</configuration>
ASP.NET網站(或稱應用程式)的提供者為AspNetSqlProvider。ASP.NET會將使用者資訊儲存在一個名為"ASPNETDB.MDF"的Microsoft SQL Server Express資料庫中。
ASPNETDB資料庫中有兩個主要用來存放使用者資訊的資料表,分別為"aspnet_Membership"、"aspnet_Users"。
Login控制項所去驗證的資料就是存放在"aspnet_Membership"和"aspnet_Users"這兩個資料表中。
要變更驗證邏輯,主要是改寫Login控制項的Authenticate事件。
Login控制項讓使用者透過他輸入使用者名稱、密碼。
LoginStatus會根據目前使用者的登入狀態\顯示不同的超連結:在使用者尚未登入或以登出的狀態下,會顯示"登入"超連結;若是使用者已登入則顯示"登出"超連結。
LoginView控制項自動偵測使用者的驗證狀態,以及角色的相關資訊,並自動呈現給使用者。
透過CreateUserWizard控制項,匿名使用者可以自行註冊成為網站的正式會員。
使用System.Web.Security.FormsAuthentication.RedirectFromLoginPage()導向原本使用者想要呼叫的網頁。
===================================================
透過Web Service,應用程式可跨網路呼叫另一台電腦上的服務。
SOAP Simple Object Access Protocol
ASP.NET會將Web應用程式目錄下每一個副檔名為.asmx的檔案視為Web Service。
每個.asmx檔案裡其實就是一個Class,只要在方法前加入[WebMethod]屬性摽式,就可讓其他應用程式或開發人員透過Internet呼叫。
Web Servic本身也是一個類別,直接繼承System.Web.Services.WebService類別,可以沿用.NET準備好的Web Service功能。
而且它必須是Public的Class,才能提供給外界使用。
只要是前面標示有[WebMethod]的方法便成為Web Service服務提供出來的一項方法。
外部應用程式透過Web Service,只能存取標示為WebMethod的公用方法。
<%@ WebService Language="C#" Class="MathWebService" %>
public class MathWebService : System.Web.Services.WebService {
[WebMethod]
public int Add(int num1, int num2)
{
return num1 + num2;
}
}
----------------------------------------
使用Web Service的方法:
瀏覽器
透過Web Service的代理程式(Proxy)
直接以Web瀏覽器瀏覽XXXX.asmx的網址,會列出所有宣告為WebMethod的方法。
.Net Framework的SDK提供了一個工具程式"webserviceutil.exe"自動產生相關的SOAP封包處理程式碼,就是所謂的代理程式(Proxy)。
在呼叫端的Web.config中可以看到參考到的Web Service的網址。
Web參考名稱 = Proxy類別的命名空間
Web參考名稱.MathWebService proxy = new Web參考名稱.MathWebService();
int result = proxy.Add(4,2);
===================================================
AJAX = Asynchronous JavaScript and XML
PostBack時會造成網頁重繪,畫面閃動,一來讓使用者眼睛不舒服,二來在PostBack時什麼都不能做,只能等待。
凡是使用到ASP.NET AJAX的網頁都必須在最前方放入一個ScriptManager。
ScriptManager.AsyncPostBackTimeout
ScriptManager.AsyncPostBackErrorMessage
若要在內容頁面存取主版頁面的ScriptManager,可呼叫ScriptManager類別的GetCurrent()方法取得。
在UpdatePanel伺服器控制項中,所發出的PostBack都會自動以AJAX的技術,透過非同步的方式傳送到Web伺服器,待伺服器將結果傳回後,再以"部分更新"的方式顯示在網頁中。
在使用UpdatePanel的情況下,伺服器只會傳回UpdatePanel中的網頁內容,UpdatePanel以外的網頁內容便不傳回。
如果真的無法將控制項全放進UpdatePanel,又希望有部分重繪效果時,可設定Trigger屬性。
每次Timer發出Tick事件,便會做一次非同步的PostBack,到伺服器上執行網頁中Page_Load程式。
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = DateTime.Now.ToString();
System.Diagnostics.PerformanceCounter pc = new System.Diagnostics.PerformanceCounter();
pc.CategoryName = "Memory";
pc.CounterName = "Available KBytes";
Label2.Text = pc.NextValue().ToString();
Image1.Width = Convert.ToInt32(Label2.Text) % 100;
Image1.Height = 20;
pc.CategoryName = "Process";
pc.CounterName = "Thread Count";
pc.InstanceName = "_Total";
Label3.Text = pc.NextValue().ToString();
Image2.Width = Convert.ToInt32(Label3.Text) % 100;
Image2.Height = 20;
}
===================================================
無論建立幾個,ASP.NET應用程式只認檔名為Web.config的組態檔,其他一律忽略。所以舊的組態檔可以不用刪除,只要變更檔名即可達到備份的效果。
XML的元素、屬性名稱大小寫不同時,就會被視為不同的元素或屬性。
<appSettings>的讀取方式有兩種:嵌入運算式或是撰寫程式。
在ASP.NET網頁裡,<%$ ... %>代表的就是一段運算式,你可將此運算式嵌入控制項的屬性裡。
Text = "<%$ AppSettings:UploadPath %>"
ConfigurationManager類別可以用來存取組態檔,他的命名空間為System.Configuration。
<%@ Import Namespace="System.Configuration" %>
string name = ConfigurationManager.AppSettings["WebSiteName"].ToString();
Expression屬性 繫結到這個控制項的屬性的運算式
若不希望打太長的類別名稱,或是要宣告許多相同命名空間下類別的物件,可先在網頁的最前面用Import前置詞將命名空間先匯入。
若要在組態檔中統一匯入命名空間,可放在<system.web><pages><namespace>...</namespace></pages></system.web>裡。
如果Web Form網頁使用程式碼分離的開發方式,還是必須在.cs檔案的最前方透過using關鍵字指定命名空間。
<system.web>
<pages>
<namespace>
<add namespace="System.Data.SqlClient" />
</namespace>
</pages>
</system.web>
啟用個別網頁的追蹤功能:
<%@ Page Language="C#" Trace="true" %>
伺服器變數是把儲存在Request.ServerVariables下的所有資料全部到出來顯示的結果。
透過Trace.Write及Trace.Warn可將自訂的字串或變數值顯示在追蹤資訊中,兩者的差別只在字型顏色,Trace.Write是用黑色,Trace.Warn是用紅色。
啟用網站層級的追蹤功能:
<system.web>
<trace enabled="true" pageOutput="true" localOnly="true" requestLimit="10" />
</system.web>
requesrLimit屬性用來設定追蹤保告儲存數量
所有追蹤的資料,都會暫存在執行環境的記憶體中,瀏覽方式只須在應用程式目錄下輸入Trace.axd即可。
.NET的組態檔有兩種:Machine.config及Web.config。組態檔所在的位置會影響設定值套用的範圍。
位於C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG目錄下的Machine.config,決定了這台電腦上所有.NET應用程式的基本組態設定和預設值。由於Machine.config檔中的設定會套用在整台電腦的.NET應用程式,影顯範圍十分廣泛,因此,若要修改其中設定必須謹慎。
Web.config組態接繼承自.NET組態階層根目錄下的Web.config。
若希望變更或是加入額外的組態,於根目錄下加入Web.config,在這個Web.config裡設定此網站專屬的組態。
透過子目錄下的組態檔可位個別子目錄設定不同的組態。
===================================================
沒有留言:
張貼留言