## HTTP
  HTTP 是一種「沒有狀態(Stateless)」的通訊協定(Protocol),Web Server 會將每個網頁的 HTTP Request 視為獨立的要求;Web Server 在預設狀況下 **"不會"** 保留先前的要求期間所使用的變數值與資訊。(伺服器不會記憶用戶端需求,而且在Response後就與伺服器斷線)
## 狀態管理的生命週期
圖片來源:MIS2000 ASP.NET專案實務
<img src="https://hackmd.io/_uploads/Sygks-FF2.png" alt="" title="" style="width:60%;margin:auto;display:block">
<br>
| 狀態 | 生命週期 | 儲存大小 | 儲存位置 | 作用對象 | 應用實例 |
| --- | --- | --- | --- | --- | --- |
| ViewState | 單一頁面 | 可透過配置調整 | 用戶端(網頁) | 頁面 | 在購物網站上填寫<br>的購物車內容 |
| Session | 關閉瀏覽器 閒置20分鐘 | 無限制<br>(看伺服器設定) | 伺服器端 | 同一瀏覽器上<br>的使用者 | 使用者登入資訊<br>購物車內容 |
| Cookies | 1000分鐘(預設)<br>可自定義時間 | 每個瀏覽器的<br>單一網域4KB | 用戶端(瀏覽器) | 同一瀏覽器上<br>的使用者 | 同一個使用者在網站上的<br>語言偏好設定、記住登入狀態 |
| Application | 直到Server關閉/重啟 | 無固定上限 | 伺服器端 | 所有使用者 | 網站的全局設定、共享的資料庫連線 |
| Cache | 無過期時間<br>自訂過期時間 | 可根據需求設定<br>大小限制 | 伺服器端 | 所有使用者 | 網頁的靜態資源(例如圖片、CSS、JavaScript檔案)的快取 |
## Application
:::info
  Application State(狀態)是一種機制,能夠儲存所有類別的資料。Application 狀態所儲存的資料都會在 **Web Server記憶體中**資料擷取及儲存上比在資料庫還要快。Application適用於所有使用者和工作階段,可以用來儲存 **少量經常使用,但不會因使用者不同而更變的資料**
:::
* Application儲存資料的大小沒有限制,取決於Server的記憶體大小,但由於Server記憶體珍貴,不建議將龐大的資料放在Application中
* Application的生命週期基本上沒有上限,除非Server端關閉,或是重新啟動,資料就會全部消失。Application存放在Server的記憶體中,當**IIS或網頁伺服器重新啟動、修改Global.asax、web.config時, Application的值便會遺失。** **(ApplicationEXP_01,ApplicationEXP_02)**
* Application狀態會將資料儲存為Object資料型別,因此如果要讀取資料時必須將資料轉換成適合的型別(Convert.To...)
```csharp!
Convert.ToInt32(Application["變數名稱"]);
```
* Application可以被多個執行緒同時存取變數,這也代表著同時間修改Application變數是可被允許的,但是這樣有可能會出現資料處理的問題像是資源競爭(Resource contention),導致資料不一致性等情況,**因此在這邊使用上Lock/Unlock,使整體窗口單一化**,也就是同一個時間內只會有一個執行緒有修改/存取的權限,而其他人則是要排隊等待。**(ApplicationEXP_03)**
>資源競爭(Resource contention)指的是多個執行緒或程序同時試圖存取或修改同一個共享資源的情況。這個共享資源可以是記憶體位置、檔案、資料庫、硬體設備或其他系統資源。
>資源競爭可能產生以下問題:
>1. 不一致性:由於存取或修改順序的不確定性,共享資源的狀態可能變得不一致,無法確定是哪個執行緒或程序的結果是正確的。
>
>2. 資料損壞:當多個執行緒同時進行寫入操作時,可能會發生資料的覆蓋或損壞,導致資料的完整性受損。
>
>3. 死鎖:如果多個執行緒相互等待對方釋放資源,而無法繼續執行,就會發生死鎖(DeadLock)。這導致系統無法繼續進行下去,需要人工介入解決。
>
<img src="https://hackmd.io/_uploads/HkjFQS0Kh.png" alt="" title="" style="width:60%;margin:auto;display:block"><br/>
圖片來源:MIS2000 ASP.NET專案實務
**以下是Application的範例:**
* ApplicationEXP_01.aspx
```csharp!
<form id="form1" runat="server">
<div>
<%
Response.Write("首先我先創造兩個變數Data_01 & Data02給Server儲存<hr>");
Application["Data_01"] = "我是 Data_01 的資料";
Application["Data_02"] = "我是 is Data_02的資料";
Response.Write("**執行完成,已導入變數**");
%>
</div>
</form>
```
* ApplicationEXP_02.aspx
```csharp!
<form id="form1" runat="server">
<div>
<%
Response.Write("這時的Application變數都已儲存在Server中<br>接著我開啟這隻網頁進行變數的讀取<hr>");
Response.Write($"<br>{Application["Data_01"]}");
Response.Write($"<br>{Application["Data_02"]}");
%>
</div>
</form>
```
* ApplicationEXP_03.aspx
```csharp!
<form id="form1" runat="server">
<div>
<%
Response.Write("Application 存放的東西,對於這個 Web 網站上所有的程式而言,通通是 \" 開放 \" 的、大家都可以 \" 共用 \",甚至進行修改。" +
"<br>所以,簡單地說 Application 是整個網站內的共用變數。<hr> ");
Application.Lock();
Application["Data_01"] = "Data_01的資料已經被修改啦!";
Application["Data_02"] = "LISJDLIASJDLIWJEW*QEU*)QW";
Application.UnLock();
Response.Write($"{Application["Data_01"]}");
Response.Write($"<br>{Application["Data_02"]}");
%>
</div>
</form>
```
## Session
圖片來源:MIS2000 ASP.NET專案實務
<br>
<img src="https://hackmd.io/_uploads/rkhbVBRYn.png" alt="" title="" style="width:60%;margin:auto;display:block"><br>
:::info
  Session與Application同樣都是屬於將資料儲存在Server的類型,而他最大的不同在於 **生命週期**以及 **作用的對象**不同
:::
*   **生命週期**:Sesstion的生命週期是有限的,預設閒置20分鐘就會失效,另外關閉瀏覽器本身也會使他失去效用。當然這部分是可以調整的(web.config 檔案中的 `<sessionState>` 元素中進行設定。)
*   **作用的對象**:在Application階段中,是對所有網站的程式進行作用,這部分包括使用不同的瀏覽器。Session 所作用的對象是使用相同瀏覽器的使用者。當使用者在同一個瀏覽器上繼續對網站進行操作時,Session 可以在不同頁面之間共享資訊。然而,當使用者切換到不同的瀏覽器或關閉瀏覽器後,Session 的資料將不再可用,因為每個瀏覽器都有自己獨立的 Session。**(SessionEXP_01,SessionEXP_02)**
*   對於Web Server來說,每一個瀏覽器都有他獨特的"SessionID",所以當不同瀏覽器開啟時,會產生出一個獨立的SessionID **(ApplicationEXP_03)**
### SessionState
  Session本身有多種模式,可以在網站中的 `Web.config`中的`mode`進行行設定
<img src="https://hackmd.io/_uploads/HJzBggoF3.png" alt="" title="" style="margin:auto;display:block">
SessionState可設定的mode屬性有以下幾種:
* **InProc**: 此模式是**預設值**無須任何撰寫,在這個模式下Session狀態會存放在Web Server記憶體進行保存
* **StateServer**: 這個模式會將Session存放在"ASP.NET狀態服務"的個別處理緒,確保Session在Web重新啟動時可以保留下來,並可以使多個Web server使用Session狀態
* **SQLServer**: 該模式會將Session儲存至SQLServer中,這樣的好處是可以保證Web在關閉或是重新啟動時Session得以保留,而且可以讓多個Server都能夠使用Session狀態
* **Custom**: 提供自訂儲存程序(Provider)的模式
* **off**: 停用Session狀態
以下是範例程式碼:
* SessionEXP_01:
```csharp!
<form id="form1" runat="server">
<div>
<%
Response.Write("首先一樣先進行變數賦值得動作<hr>");
Session["Data_03"] = "我是Data_03!";
Session["Data_04"] = "Data_0004";
Response.Write("**變數賦值完畢**");
%>
</div>
</form>
```
* SessionEXP_02:
```csharp!
<form id="form1" runat="server">
<div>
<%
Response.Write($"{Session["Data_03"]}<br>");
Response.Write($"{Session["Data_04"]}");
%>
</div>
</form>
```
* SessionEXP_03:
```csharp!
<form id="form1" runat="server">
<div>
<%
Response.Write("作用於不同的瀏覽器會有不同的SessionID<hr>");
Response.Write($"Session.SessionID = {Session.SessionID}");
%>
</div>
</form>
```
### 補充(2023/10/18)
**ASP.NET WebForms的Session安全疑慮**
WebForms中,session ID是自動生成,但是確保安全性的責任仍在開發者。以下為在保護session的完整性和隱私性的一些方法:
使用HTTPS:HTTPS加密客戶端和伺服器間的通訊,以保護session ID和其他敏感數據不被攔截。您應該確保您的Web Forms應用程序始終在HTTPS上運行。
* 配置session cookie屬性:
* 使用Secure屬性確保cookie只在HTTPS上被發送。(Global.asax)
```csahrp!
protected void Session_Start(Object sender, EventArgs e)
{
// 檢查如果已經有session cookie
if (Response.Cookies["ASP.NET_SessionId"] != null)
{
// 設定Secure和HttpOnly屬性
Response.Cookies["ASP.NET_SessionId"].Secure = true;
Response.Cookies["ASP.NET_SessionId"].HttpOnly = true;
}
}
```
* HttpOnly屬性:在web.config中添加防止JavaScript訪問cookie,從而減少跨站腳本XXS攻擊的風險。
```xml
<httpCookies httpOnlyCookies="true" requireSSL="true" />
```
* 設定session超時:在web.config添加限時可以確保未使用的session在設定的時間後過期。例如,設置20分鐘的超時:
```xml
<sessionState mode="InProc" cookieless="UseCookies" timeout="20" />
```
* 登出時銷毀session:當用戶登出時,應該銷毀session,確保其數據不被未經授權的用戶訪問。程式碼中可以這樣做:
```csharp!
Session.Abandon();
```
* anti-CSRF令牌:利用ASP.NET Web Forms的內置功能來防止跨站請求偽造。當進行敏感操作時,確保部署這些令牌。(尚待研究)
* 避免將敏感信息存儲在session中:如果真的有這個需要,應考慮加密這些信息,確保即使session被竊取,數據也無法被解密。
* 保持更新:定期更新您的ASP.NET應用程序和伺服器環境,以確保任何已知的安全漏洞已經被修復。
* 避免**顯示詳細錯誤頁面**,盡量大量使用跳轉的方式防止駭客知道軟體框架,進而破解
## Cookie
:::info
  Cookie是提供Web儲存使用者特定資訊的一種方法,像是當使用者造訪網站時,可以使用Cookie儲存使用者偏好設定或其他資訊,當使用者下次造訪網站時WEB可以擷取Cookie儲存的資訊。
:::
* Cookie本身與Session有很密切的關係,如果使用者把瀏覽器設定為禁用 Cookie 的話,大部分的 Session 功能也會終止。
* Cookie是一段小文字,它在網站伺服器和瀏覽器之間傳遞。當使用者要求瀏覽網站的網頁時,除了傳送網頁內容外,伺服器還會傳送一個包含日期和時間的Cookie。當使用者的瀏覽器接收到網頁時,也會同時接收並保存在使用者的資料夾中。
* **Cookie與網站(Website)息息相關,而不是與特定網頁(Page)有關聯**,因此不論使用者從網站要求的網頁為何,瀏覽器和伺服器"都會"交換 Cookie 資訊。當使用者造訪不同的網站時,每個網站也會將 Cookie 傳送至使用者的瀏覽器。使用者的瀏覽器會「分開儲存」所有的 Cookie。
* 大部分瀏覽器支援" 最多 "4,096 位元組的 Cookie。因為這項容量大小限制,所以 Cookie 最好用來儲存" 少量 "
* 當建立 Cookie 時,您會指定Name和Value。每個Cookie都必須有唯一的"名稱",以便稍後從瀏覽器讀取時能夠識別它。==**因為Cookie是使用"名稱 "儲存,所以將兩個Cookie命名為相同名稱時,會導致其中一個被覆寫(被蓋掉)**==。 可以在瀏覽器的"檢查中"找到該網頁所有的Cookie。**(CookieEXP_01、CookieEXP_LOGIN 、Cookie_LOGIN_END)**

| 常用屬性 | 敘述 |
| -------- | -------- |
| ResPonse.Cookie["Name"].Value | 生成一個Cookie,並以Name作為辨識,及Value為Cookie的內容 |
|ResPonse.Cookie["Name"].Expires|幫指定"Name的Cookie<br>賦予有效期限|
以下是範例程式碼:
* **CookieEXP_01**
```csharp!
<form id="form1" runat="server">
<div>
<%
Response.Write("在這邊添加一個Cookie<br>它的名稱是\"Cookie_01\"<br>內容的Value是\"I am a Cookie\"<br>最後幫Cookie加上有效期限15天<hr>");
Response.Cookies["Cookie_01"].Value = "I am a Cookie";
Response.Cookies["Cookie_01"].Expires = DateTime.Now.AddDays(15);
Response.Write("**Cookie產生完畢**");
%>
</div>
</form>
```
* CookieEXP_LOGIN.aspx
```csharp!
<form id="form1" runat="server">
<div>
帳號密碼分別是123/456<hr/>
帳號:<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><br/>
<p/>
密碼:<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox><br/>
<asp:Button ID="Button1" runat="server" Text="登入" OnClick="Click" />
</div>
</form>
```
* CookieEXP_LOGIN.aspx.cs
```csharp!
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Click(object sender, EventArgs e)
{
if (TextBox1.Text == "123" && TextBox2.Text == "456")
{
Response.Cookies["Login"].Value ="OK";
Response.Cookies["Login"].Expires = DateTime.Now.AddDays(30);
Response.Cookies["UserName"].Value = TextBox1.Text;
Response.Redirect("CookieEXP_Login_end.aspx");
}
else
{
Response.Write("帳號密碼輸入錯誤,請重新輸入");
}
}
```
* CookieEXP_Login_end.aspx
```csharp!
<form id="form1" runat="server">
<div>
<%
if (Request.Cookies["Login"] != null)
{
if (Request.Cookies["Login"].Value == "OK")
{
Response.Write("<h3>恭喜成功登入</h3>");
}
else
{
Response.Write("<h3 style=\"color:red;\">非法登入,請用正常登入作業</h3>") ;
Response.End();
}
}
else
{
Response.Write("<h3>非法登入,請用正常登入作業</h3>");
Response.End();
}
%>
</div>
</form>
```
## Cache
:::info
  Cache(緩存)是一種用於儲存資料的機制,通常會將需要頻繁調用的伺服器資源物件存儲在記憶體中。這些資源可以是數據庫查詢結果、計算結果、網頁內容或其他需要被重複使用的資料。資料本身會存儲在記憶體中,網頁或應用程式就可以快速的獲取資料,不需每次都去查詢或計算。進而提升網站或應用程式的效能和速度,因為從記憶體中讀取資料比從資料庫或其他資源中讀取要快得多。
:::
* ==它存儲於伺服器的記憶體中==,並允許自定義如何緩存項以及將它們緩存多長時間,當缺乏系統記憶體時,緩存會自動移除很少使用的或優先順序較低的項以釋放記憶體,該技術也稱為清理,這是緩存確保過期資料不使用寶貴的伺服器資源的方式之一。
* 要將資料放入Cache,可以用[Insert](http://msdn2.microsoft.com/zh-tw/library/system.web.caching.cache.insert%28VS.80%29.aspx)或[Add](http://msdn2.microsoft.com/zh-tw/library/system.web.caching.cache.add%28VS.80%29.aspx),二者最大的不同是==Insert時會不論Cache中是否已有該Key值的CacheItem時,一律新增或覆寫為傳入的value;而Add在Cache中已存在該Key時,會直接傳回現有物件,不做更新==。**(CacheEXP_01)**
| 常用語法 | 用途 |
|-|-|
| Cache\["Name"\] = "Value" | 一般用於Cache賦值 |
| Cache.Insert("Name","Value") | 使用Insert進行賦值 |
| String VariableName = Cache\["Name"\].ToString(); | 讀取Cache值 |
| Cache.Remove("Name") | 用於移除Cache |
以下是範例程式碼:
* CacheEXP_01
```csharp!
<form id="form1" runat="server">
<div>
<%
Cache["Name"] = "Kaz";//一般Cache賦值
Cache.Insert("Food", "Apple");//使用"Insert"對Cache賦值
Response.Write($"{Cache["Name"]}<br>");//讀取Cache值
Response.Write($"原始的Food={Cache["Food"]}<br>");
Cache.Remove("Name");//移除數據
if (Cache["Name"] == null)
{
Response.Write("\"Name\"已被移除<br>");
}
else { Response.Write(Cache["Name"]); }
Cache.Insert("Food", "Banana");//Insert具有可以賦寫的特性
Response.Write($"使用Insert後的Food={Cache["Food"]}<br>");
//而使用Add的情況Add會視該名稱的Cache有沒有值,若是沒有則加上去
//但是已經有值的情況為維持其值不變
Cache.Add("Food", "PinApple", null, DateTime.Now.AddMinutes(10), TimeSpan.Zero, CacheItemPriority.Normal, null);
Response.Write($"使用Add後的Food={Cache["Food"]}<br>");
%>
</div>
</form>
```
## ViewState
:::info
ViewState 是 ASP.NET Web Forms 中的一個儲存機制,用於在不使用外部儲存機制(如伺服器或資料庫)的情況下,儲存網頁的狀態。它允許網頁與伺服器之間進行通信,以記住網頁的狀態並在後續的請求中保持一致。
:::
  Web控制項中的Label控制項可以幫我們記住數值並且記錄在網頁中的這是因為**Label會將資料放置 **"VIEWSTATE"(視圖)** 中進行儲存**。當我按下按鈕後,他會將按下的次數記錄在VIEWSTATE中,再傳回去給Server,而Server知道了VIEWSTATE的次數後再配合Button按下之後+1並再回傳給電腦,這樣SerVer端就不用記憶了,**等於是Server與瀏覽器之間的暫存記憶**,但這也意味著如果資訊量越大,而這個暫存記憶的亂碼也會相對增加,而這段亂碼本身是"有編碼無加密的"代表這段亂碼可藉由編碼產生資訊 **(WebControls)**
``` mermaid
graph TD
按下按鈕(Button)-->記錄按下次數到VIEWSTATE;
記錄按下次數到VIEWSTATE-->傳送至Server;
傳送至Server-->Server接收VIEWSTATE;
Server接收VIEWSTATE-->VIEWSTATE+1;
VIEWSTATE+1-->回傳至電腦;
```

* ==ViewState的生命週期僅限於"網頁(Page)"當下,當網頁被關閉時就會消失==。
* 另外Lebel屬性中有一個屬性EnableViewState,預設值為True。當這個屬性調整為False時,可以注意到當我連點Button時僅第一下網頁會觸發+1在這之後就無法+1了,也就代表這個Label失去了暫時儲存的功能。
## What is PostBack
:::info
  PostBack 是 [ASP.NET](http://ASP.NET) Web Forms 中的一個概念,它是指在網頁上觸發了某個事件(如按下一個按鈕),伺服器會重新載入該網頁,並重新執行整個頁面的生命週期,以便處理該事件。
在 PostBack 過程中,[ASP.NET](http://ASP.NET) 會將網頁上的所有控制項的狀態保存在 ViewState 中,以便在伺服器重新載入網頁時能夠恢復這些控制項的狀態。**(WebControls)**
:::
### 要怎麼判斷這一次Request是不是PostBack?
==可以使用`IsPostBack`屬性來判斷當前的請求是否為PostBack。==
在Web Forms頁面(.aspx)中,你可以在伺服器端的程式碼中使用`IsPostBack`屬性。例如,在Page_Load事件中檢查該屬性:
**(WebControls)**
```csharp!
protected void Page_Load(object sender, EventArgs e)
{
Label3.Text = Application["VisitorsCount"].ToString();
if (IsPostBack)
{
Label4.Text = "觸發PostBack";
}
else
{
Label4.Text = "無PostBack反應";
}
}
```
### 哪一些控制項有AutoPostBack 按下webform 上面的按鈕,依序會觸發哪一些頁面事件?
**AutoPostBack 屬性(部分控制項才有此屬性)**:表示這個控制項的內容一 旦被更動或是選用,就會將資料自動提交出去(送回 Web Server)。傳統的 HTML 表單必須按下「提交(Submit)」按鈕或相關程式,才會將資料送回 Web Server。
**EnableViewState 屬性**:當我們填寫資料並將資料提交(Submit)出去之後。
- 必須啟用伺服器控制項的檢視狀態,在HTTP要求(Request)之間保持其狀態。
- 伺服器控制項的檢視狀態(ViewState)是它全部屬性值的累積。為了在 HTTP 的每一次要求(Request)之間保留這些值,**[ASP.NET](http://asp.net/) 使用 StateBag 類別的執行個體來儲存屬性值。數值接著在處理後續的要求 時,會當做變數傳遞至「隱藏欄位(如 <input type="hidden">)」。**
以下是具有AutoPostBack屬性的正確控制項清單:
- Button(按鈕)
- LinkButton(連結按鈕)
- ImageButton(圖像按鈕)
- CheckBox(勾選框)
- RadioButton(單選按鈕)
- TextBox(文本框)
- DropDownList(下拉列表)
- ListBox(列表框)
- CheckBoxList(勾選框列表)
- RadioButtonList(單選按鈕列表)
- Calendar(日曆控制項)
- FileUpload(文件上傳控制項)
當這些控制項的AutoPostBack屬性設置為true時,用戶對它們進行操作(例如單擊按鈕、選擇下拉列表項目等)將導致整個頁面進行回發(PostBack)並觸發相應的事件。**(WebControls)**
在WebForms中,當按下按鈕並設置了AutoPostBack屬性為true時,會觸發以下事件的順序:
:::info
1. Page_Init:頁面初始化事件,用於初始化頁面的控件和狀態。
2. Control_Init:控制項初始化事件,用於初始化按鈕及其相關的控件。
3. Control_Load:控制項加載事件,用於加載控制項的狀態和數據。
4. Page_Load:頁面加載事件,用於加載頁面的狀態和數據。
5. Button_Click:按鈕點擊事件,即按鈕被點擊時觸發的事件。
6. Control_PreRender:控制項預渲染事件,用於準備控制項的最終呈現狀態。
7. Page_PreRender:頁面預渲染事件,用於準備頁面的最終呈現狀態。
:::
``` mermaid
graph TD
id2(Page_Init)-->Control_Init;
Control_Init-->Control_Load;
Control_Load-->Page_Load;
Page_Load-->Button_Click;
Button_Click-->Control_PreRender;
Control_PreRender-->Page_Render;
```
**最後附上WebControls演示範例(WebControls.aspx)**
* WebControls.aspx
```html!
<body style="background-color: #181a1b; color: antiquewhite">
<form id="form1" runat="server" style="display: flex; flex-wrap: wrap; justify-content: center">
<div style="width: 300px; text-align: center; padding: 5px;">
<h3 style="text-align: center">1.Label & Literal</h3>
<p>是否有AutoPostBack屬性:NO</p>
<p>是否有EnableViewState屬性:YES</p>
<p style="text-align: left; color: green">  Label & Literal的差異在於 Label支援CSS/HTML及後置程式碼樣式,而Literal僅單純是以純文字表示</p>
Label:<asp:Label ID="Label1" runat="server" Text="0"></asp:Label><br />
<p />
Literal:<asp:Literal ID="Literal1" runat="server" Text="0"></asp:Literal><br />
<p />
</div>
<div style="width: 300px; text-align: center; padding: 5px;">
<h3 style="text-align: center">2.TextBox</h3>
<p>是否有AutoPostBack屬性:YES</p>
<p>是否有EnableViewState屬性:YES</p>
<p style="text-align: left; color: green">  TextBox中有一個屬性是"TextMode",可以選擇不同模式來管理各種TextBox可預見的情況</p>
PassWord Mode--<asp:TextBox ID="TextBox1" runat="server" TextMode="Password"></asp:TextBox>
<p />
Email-Mode--<asp:TextBox ID="TextBox2" runat="server" TextMode="Email"></asp:TextBox>
<p />
MultiLine-Mode--<asp:TextBox ID="TextBox3" runat="server" TextMode="MultiLine"></asp:TextBox>
<p />
</div>
<div style="width: 300px; text-align: center; padding: 5px;">
<h3 style="text-align: center">3.Image</h3>
<asp:Image ID="Image1" runat="server" ImageUrl="https://media.discordapp.net/attachments/752895898576748626/1073789300623298640/gifntext-gif-1--unscreen.gif" />
</div>
<div style="width: 300px; text-align: center; padding: 5px;">
<h3 style="text-align: center">4.HyperLink</h3>
<p>是否有AutoPostBack屬性:NO</p>
<p>是否有EnableViewState屬性:YES</p>
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="https://www.google.com">這是一個股哥連結</asp:HyperLink>
</div>
<br />
<div style="width: 300px; text-align: center; height: 330px; padding: 5px;">
<h3 style="text-align: center">5.Button</h3>
<p>是否有AutoPostBack屬性:YES(內建)</p>
<p>是否有EnableViewState屬性:YES</p>
<asp:Button ID="Button2" runat="server" Text="快幫我+1" OnClick="Button2_Click" EnableViewState="True" /><br />
<span style="color: red">行為是否PostBack:<asp:Label ID="Label4" runat="server" Text=""></asp:Label></span>
</div>
<div style="width: 300px; text-align: center; padding: 5px;">
<h3 style="text-align: center">6.LinkButton</h3>
<p>是否有AutoPostBack屬性:YES(內建)</p>
<p>是否有EnableViewState屬性:YES</p>
點擊次數:<asp:Label ID="Label3" runat="server" Text="0" Visible="True">點擊次數</asp:Label>
<p style="text-align: left; color: green">  LinkButton與HyperLink非常相似,最大差異在於LinkButton本身有"OnClick"事件可以添加,HyperLink沒有</p>
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="Link_Click" Text="LinkButton">這是一個股哥連結</asp:LinkButton>
</div>
<div style="width: 300px; text-align: center; padding: 5px;">
<h3 style="text-align: center">7.ImageButton</h3>
<p>是否有AutoPostBack屬性:YES(內建)</p>
<p>是否有EnableViewState屬性:YES</p>
<asp:ImageButton ID="ImageButton1" runat="server" ImageUrl="https://i.pinimg.com/564x/4a/23/cd/4a23cdd9fbab98eea67252bf62fe6270.jpg" Width="120px" OnClick="Link_Click" />
</div>
<div style="width: 300px; text-align: center; padding: 5px;">
<h3 style="text-align: center">8.Dropdownlist</h3>
<p>是否有AutoPostBack:YES</p>
<p>是否有EnableViewState屬性:YES</p>
<p style="text-align: left; color: green">  這段範例中我做了一個自訂新增的功能,使用"OnSelectedIndexChanged"事件<br/>在後置加入"DropDownList.Items.Add()"方法添加項目</p>
<asp:DropDownList ID="DropDownList1" runat="server" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged" AutoPostBack="True">
<asp:ListItem Text="1" />
<asp:ListItem Text="自己的項目自己加" Value="New"/>
</asp:DropDownList><br/>
<asp:TextBox ID="TextBox4" runat="server" Visible="False"></asp:TextBox>
<asp:Button ID="Button3" runat="server" Text="新增項目" Visible="False" OnClick="Click_AddItem" />
</div>
<br />
<div style="width: 300px; text-align: center; height: 330px; padding: 5px;">
<h3 style="text-align: center">9.CheckBox</h3>
<p>是否有AutoPostBack:YES</p>
<p>是否有EnableViewState屬性:YES</p>
<asp:CheckBox ID="CheckBox1" runat="server" Text="缺罷課斯1"/><br/>
<asp:CheckBox ID="CheckBox2" runat="server" Text="缺罷課斯2"/><br/>
<asp:CheckBox ID="CheckBox3" runat="server" Text="缺罷課斯3"/><br/>
<asp:CheckBox ID="CheckBox4" runat="server" Text="缺罷課斯4"/><br/>
</div>
<div style="width: 300px; text-align: center; padding: 5px;">
<h3 style="text-align: center">10.CheckBoxList</h3>
<p>是否有AutoPostBack:YES</p>
<p>是否有EnableViewState屬性:YES</p>
<asp:CheckBoxList ID="CheckBoxList1" runat="server">
<asp:ListItem Text="text1" />
<asp:ListItem Text="text2" />
<asp:ListItem Text="text3" />
<asp:ListItem Text="text4" />
<asp:ListItem Text="text6" />
</asp:CheckBoxList>
</div>
<div style="width: 300px; text-align: center; padding: 5px;">
<h3 style="text-align: center">11.RadioButton</h3>
<p>是否有AutoPostBack屬性:YES</p>
<p>是否有EnableViewState屬性:YES</p>
<p style="text-align: left; color: green">  在這段範例中我特地將RadioButton中的AutoPostBack屬性開啟代表當我按下按鈕時會觸發PostBack並叫Label幫我將所選的項目儲存並顯示在畫面上</p>
<asp:RadioButton ID="RadioButton1" runat="server" Text="我是選項1" OnCheckedChanged="Checked" AutoPostBack="True" /><br />
<asp:RadioButton ID="RadioButton2" runat="server" Text="我是選項2" OnCheckedChanged="Checked" AutoPostBack="True" /><br />
<asp:RadioButton ID="RadioButton3" runat="server" Text="我是選項3" OnCheckedChanged="Checked" AutoPostBack="True" /><br />
<asp:RadioButton ID="RadioButton4" runat="server" Text="我是選項4" OnCheckedChanged="Checked" AutoPostBack="True" /><br />
<asp:Label ID="Label2" runat="server" Text="您所選的項目:<br>"></asp:Label><br />
</div>
<div style="width: 300px; text-align: center; padding: 5px;">
<h3 style="text-align: center">12.RadioButtonList</h3>
<p>是否有AutoPostBack屬性:YES</p>
<p>是否有EnableViewState屬性:YES</p>
<asp:RadioButtonList ID="RadioButtonList1" runat="server">
<asp:ListItem Text="List1" />
<asp:ListItem Text="List2" />
<asp:ListItem Text="List3" />
<asp:ListItem Text="List4" />
</asp:RadioButtonList>
</div>
</form>
</body>
```
WebControls.aspx.cs
```csharp!
protected void Page_Load(object sender, EventArgs e)
{
Label3.Text = Application["VisitorsCount"].ToString();
if (IsPostBack)
{
Label4.Text = "觸發PostBack";
}
else
{
Label4.Text = "無PostBack反應";
}
}
protected void Button2_Click(object sender, EventArgs e)
{
int a = Convert.ToInt32(Label1.Text) + 1;
int b = Convert.ToInt32(Literal1.Text) + 1;
Label1.Text = a.ToString();
Literal1.Text = b.ToString();
Button2.Text = $"快點幫我讓Label+1!!({a.ToString()}))";
Random rn = new Random();
Label1.ForeColor = Color.FromArgb(rn.Next(0, 255), rn.Next(0, 255), rn.Next(0, 255));
}
protected void Checked(object sender, EventArgs e)
{
CheckBox ckb = (CheckBox)sender;
Label2.Text += $"{ckb.Text}<br>";
}
protected void Link_Click(object sender, EventArgs e)
{
Application.Lock();
Application["VisitorsCount"] = (int)Application["VisitorsCount"] + 1;
Application.UnLock();
Response.Redirect("https://www.google.com");
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
if(DropDownList1.SelectedValue == "New")
{
TextBox4.Visible = true;
Button3.Visible = true;
}
}
protected void Click_AddItem(object sender, EventArgs e)
{
ListItem li = new ListItem();
li.Text = "asdasdasdasd";
DropDownList1.Items.Add(li);
TextBox4.Visible = false;
Button3.Visible = false;
}
```
## What is GET & POST? 比較GET/POST的差異
### HTTP Method
  我們先說明一下 HTTP Method,在 HTTP 1.1 的版本中定義了八種 Method (方法),如下所示:
- OPTIONS
- GET
- HEAD
- POST
- PUT
- DELETE
- TRACE
- CONNECT
Http定義了與伺服器交互的不同方法,最基本的方法有4種,分別是GET、POST、PUT、DELETE
URL全稱是資源描述符,我們可以這樣認為:一個URL位址,它用於描述一個網路上的資源,**而HTTP中的GET,POST,PUT,DELETE就對應著對這個資源的查詢,修改,新增,刪除4個操作。**
### POST & GET Method
  我們使用的表單只用了其中兩個方法 (GET/POST),POST和GET是在網路上常用的兩種資料傳輸方式,可以用以下方式解釋:
:::warning
書籍借閱:
* GET: 直接的與對象詢問是否有這本書籍,而對方直接的再將書提供給你,而這段過程大家都看的到(GET的資料會直接的顯示在網址例如:〝https://medium.com/?id=010101〞)
* POST:先將詢問借書的對象寫在信封,並將要借閱的書籍放在信封中(私密性,**瀏覽器的網址沒有變化**),資料放在Message-body中),對方看到後再將書提供給你,這段過程外部人士不會知道事情的經過
:::
GET就像直接問別人要東西,POST則是通過一個間接的媒介來傳達你的需求。在網路上,使用GET方法時,資料會顯示在網址中,而使用POST方法時,則是透過請求的主體(Request Body)來傳遞資料。
| 差異點 | GET | POST |
| --- | --- | --- |
| 參數傳遞位置 | 通過URL的查詢字符串(Query String)傳遞 | 通過請求體傳遞(Request body) |
| 參數長度限制 | URL有長度限制(一般不超過2048個字元) | 沒有長度限制 |
| 安全性 | 參數明文出現在URL中 | 參數不會直接顯示在URL中 |
| 快取 | 可以被瀏覽器快取 | 通常不會被瀏覽器快取 |
>Request-body(請求主體)是在HTTP請求中用於傳遞請求資料的一部分。當您發送HTTP請求時,請求主體是放置在請求的主要內容區域,用於傳遞附加的資料,例如表單數據、JSON資料、檔案上傳等。
>
>請求主體通常在POST、PUT、PATCH等請求方法中使用,這些方法需要將資料傳送到伺服器。請求主體的格式可以根據所使用的內容類型(Content-Type)來定義,例如application/x-www-form-urlencoded、multipart/form-data、application/json等。
**GET一般用於獲取/查詢 資源資訊,而POST一般用於更新資源資訊(個人認為這是GET和POST的本質區別,也是協議設計者的本意,其它區別都是具體表現形式的差異 )。**
**以下是一些有關GET & POST的特性:**
* GET在瀏覽器回退時是無害的,而POST會再次提交請求。
* GET產生的URL地址可以被Bookmark,而POST不可以。
* GET請求會被瀏覽器主動cache,而POST不會,除非手動設置。
* GET請求只能進行url編碼,而POST支持多種編碼方式。
* GET請求參數會被完整保留在瀏覽器歷史記錄裡,而POST中的參數不會被保留。
* GET請求在URL中傳送的參數是有長度限制的,而POST麼有。
* 對參數的數據類型,GET只接受ASCII字符,而POST沒有限制。
* GET比POST更不安全,因為參數直接暴露在URL上,所以不能用來傳遞敏感信息。 GET參數通過URL傳遞,POST放在Request body中。
### 我要如何知道的是POST還是GET?
* F12開啟Devools檢視並用預覽來看自己想了解的內容,假如我想知道部落格的內文屬於哪種方式,之後點選標頭來看網頁使用哪一種方法提供資料


## HTTP Header
>Reference From Rick's Note:
> https://www.notion.so/Header-ee39814398554fb5a734ba981e9c8694
:::info
  HTTP使用Request/ResPonse方式讓使用者對伺服器端進行要求,並由伺服器端回應至用戶端產生畫面,網路資源的傳輸主要為訊息頭(message-header)和訊息體(message-body)兩部分。
:::
>訊息體(message-body)就是實際的資料內容,例如HTML文件、圖片、JSON數據等。訊息體的存在與否取決於具體的HTTP請求或回應,並且在一個HTTP請求或回應中可以有或沒有訊息體。
訊息頭,即HTTP頭訊息,HTTP頭訊息被分幾個類型:
1. **通用標頭(General Headers)** 在HTTP請求和響應中傳遞通用的資訊。它們提供了與請求和響應的整體處理相關的資訊。
- Cache-Control:控制緩存的行為,例如指定是否允許緩存、緩存的有效期等
- 範例:**`Cache-Control: max-age=3600`**
- Connection:指定是否保持連接或關閉連接
- 範例:**`Connection: keep-alive`**
- Date:表示消息的日期和時間
- 範例:**`Date: Wed, 12 May 2021 10:30:00 GMT`**
- Upgrade-Insecure-Requests:指示瀏覽器在請求時將不安全的HTTP URL自動升級為安全的HTTPS URL
- 範例:**`Upgrade-Insecure-Requests: 1`**
2. **請求標頭(Request Headers)** 在HTTP請求中用於傳遞附加資訊的資料。它們提供有關客戶端請求的相關資訊,例如所需的內容類型、瀏覽器的資訊、語言偏好等。
- Accept:指定客戶端可以接受的內容類型
- 範例:**`Accept: text/html, application/json`**
- Accept-Encoding:指定客戶端可以接受的壓縮方式
- 範例:**`Accept-Encoding: gzip, deflate`**
- Accept-Language:指定客戶端可以接受的語言
- 範例:**`Accept-Language: en-US, zh-TW`**
- Authorization:包含用於身份驗證的憑證信息
- 範例:**`Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...`**
- Cookie:包含由伺服器發送的Cookie
- 範例:**`Cookie: sessionid=abc123; username=johndoe`**
- User-Agent:指定發起請求的用戶代理(瀏覽器、軟體或爬蟲)的資訊
- 範例:**`User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36`**
- Referer:指示請求的來源URL
- 範例:**`Referer: https://www.example.com/page1.html`**
3. **回應標頭(Response Headers)** 描述HTTP伺服器回應的相關資訊。回應標頭提供了關於回應的資料,例如回應的狀態碼、內容類型、緩存控制等。
- Content-Type:指定回應主體的媒體類型
- 範例:**`Content-Type: text/html; charset=UTF-8`**
- Content-Encoding:指定回應檔案的編、解碼
- 範例:**`Content-Encoding: gzip`**
- Content-Language:指定回應主體的自然語言
- 範例:**`Content-Language: en-US`**
- Content-Length:指定回應主體的長度(以字節為單位)
- 範例:**`Content-Length: 1024`**
- Expires:指定回應的到期日期和時間
- 範例:**`Expires: Wed, 12 May 2021 10:30:00 GMT`**
- Last-Modified:指示回應主體的最後修改日期和時間
- 範例:**`Last-Modified: Wed, 12 May 2021 08:00:00 GMT`**
- Server:指示伺服器的軟體和版本
- 範例:**`Server: Apache/2.4.29 (Unix)`**
**以下是一些其他Header:**
| Header | 解釋 | 範例 |
| --- | --- | --- |
| Accept-Ranges | 表明伺服器是否支援指定範圍的請求以及哪種類型的分段請求 | Accept-Ranges: bytes |
| Age | 從原始伺服器到代理快取形成的估計時間(以秒計,非負數) | Age: 12 |
| Allow | 對某網路資源的有效請求行為,不允許則返回405 | Allow: GET, HEAD |
| Cache-Control | 告訴所有的快取機制是否可以快取及哪種類型 | Cache-Control: no-cache |
| Content-Encoding | 網頁伺服器支援的返回內容壓縮編碼類型 | Content-Encoding: gzip |
| Content-Language | 回應體的語言 | Content-Language: en,zh |
| Content-Length | 回應體的長度 | Content-Length: 348 |
| Content-Location | 請求資源可替代的備用另一地址 | Content-Location: /index.htm |
| Content-MD5 | 返回資源的MD5校驗值 | Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== |
| Content-Range | 在整個回應體中本部分的位元組位置 | Content-Range: bytes 21010-47021/47022 |
| Content-Type | 返回內容的MIME類型 | Content-Type: text/html; charset=utf-8 |
| Date | 原始伺服器訊息發出的時間 | Date: Tue, 15 Nov 2010 08:12:31 GMT |
| ETag | 請求變數的實體標籤目前的值 | ETag: “737060cd8c284d8af7ad3082f209582d” |
| Expires | 回應過期的日期和時間 | Expires: Thu, 01 Dec 2010 16:00:00 GMT |
| Last-Modified | 請求資源的最後修改時間 | Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT |
| Location | 用來重新導向接收方到非請求URL的位置以完成請求或標識新的資源 | Location: http://www.zcmhi.com/archives/94.html |
| Pragma | 包括實現特定指令,它可應用到回應鏈上的任何接收方 | Pragma: no-cache |
| Proxy-Authenticate | 它指出認證方案和可應用到代理的該URL上的參數 | Proxy-Authenticate: Basic |
| Refresh | 應用於重新導向或一個新的資源被創造,在5秒之後重新導向 | Refresh: 5; url= http://www.zcmhi.com/archives/94.html |
| Retry-After | 如果實體暫時不可取,通知客戶端在指定時間之後再次嘗試 | Retry-After: 120 |
| Server | 網頁伺服器軟體名稱 | Server: Apache/1.3.27 (Unix) (Red-Hat/Linux) |
| Set-Cookie | 設定HTTP Cookie | Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1 |
| Trailer | 指出頭域在分塊傳輸編碼的尾部存在 | Trailer: Max-Forwards |
| Transfer-Encoding | 檔案傳輸編碼 | Transfer-Encoding: chunked |
| Vary | 告訴下游代理是使用快取回應還是從原始伺服器請求 | Vary: * |
| Via | 告知代理客戶端回應是通過哪裡傳送的 | Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
| Warning | 警告實體可能存在的問題 | Warning: 199 Miscellaneous warning |
| WWW-Authenticate | 表明客戶端請求實體應該使用的授權方案 | WWW-Authenticate: Basic |
### 如何用瀏覽器查看網站的Request Header與Response Header
* F12開啟DevTool並選擇網路,並在想要知道的項目點選標頭(Header)即可知道標頭內容

這邊補充一下,一般(General)標頭並不是指通用標頭,而是指通用的資訊,例如請求或回應的HTTP版本、請求方法和狀態碼等。這些資訊可以視為屬於一般範疇的標頭資訊。
* **狀態碼(Status Code)**:指示請求的處理結果,如200表示成功,404表示資源未找到,500表示伺服器錯誤等。
* **請求方法(Request Method)**:指定要執行的動作,例如GET、POST、PUT、DELETE等。
## 網路常用物件
### Page
:::info
Page是ASP.NET WebForm中的基礎頁面,他提供了一個容器用於容納訊息主體及事件模型,用於處理用戶輸入和其他操作
:::
* 在每個ASP.NET WebForm專案中 每個網頁都是一個Page物件
* Page負責處理網頁的生命週期和狀態管理
* Page的Code Behind中都設有Page_Load事件,用於執行網頁初始化

```csharp!
<%@ Page
Language="C#" // 使用C#語言
AutoEventWireup="true" // 自動呼叫網頁的讀取事件,預設是true
CodeBehind="WebForm1.aspx.cs" // 網頁程式碼的後置檔案
Inherits="test123.WebForm1" %> // 網頁類別的名稱
```
### Server
:::info
Server物件是ASP.NET框架中的一個核心類別,**提供了各種功能和方法,用於處理網頁操作和相關的服務。**
:::
- **網頁控制項操作**:透過Server物件,可以執行各種網頁控制項的操作。例如,使用`Server.FindControl`方法可以根據ID查找特定的控制項,而`Server.Execute`方法則可以執行另一個網頁,並將結果返回到當前網頁。此外,Server物件還提供了方法來操作控制項的可見性、啟用狀態和數據繫結等。
- **網頁生命週期管理**:ASP.NET中的網頁生命週期是指網頁從被請求到最終呈現給用戶的整個過程。Server物件在網頁生命週期的不同階段提供了相應的事件和方法,用於處理和管理網頁的行為。例如,` Server.Transfer`方法可以在不同生命週期中將請求轉發到另一個網頁。
- **檔案和資源操作**:Server物件還提供了用於處理檔案和資源的方法。使用`Server.MapPath`方法可以獲取檔案的實際物理路徑,以進行檔案操作。此外,Server物件還提供了`Server.MapPath`方法來獲取資源檔案(例如圖片、CSS、JavaScript等)的URL,以便在網頁中引用這些資源。
例如 `<img src="<%= Server.MapPath("~/Images/logo.png") %>" />`。
Server物件在ASP.NET中扮演著重要的角色,它為開發者提供了方便且強大的方法,用於處理網頁操作、管理網頁生命週期和操作檔案資源。透過Server物件,開發者可以輕鬆地實現各種功能和處理用戶的需求。
### Response
:::info
Response物件是ASP.NET框架中的重要類別,**用於處理伺服器對客戶端的回應。**
:::
- 輸出內容:透過Response物件,可以向客戶端發送各種類型的回應內容。使用`Response.Write`方法可以直接向網頁輸出文字或HTML標記。而`Response.Redirect`方法則可以將請求重新導向到另一個URL。
```csharp!
Response.Write("Hello, World!");
```
```csharp!
Response.Redirect("Page2.aspx");
```
- 設定回應標頭:Response物件還提供了方法和屬性,用於設定回應的標頭信息。例如,使用`Response.ContentType`屬性可以設定回應的內容類型(例如,`text/html`表示回應是HTML文件,`application/json`表示回應是JSON數據。),而`Response.AddHeader`方法可以添加自定義的標頭信息。
```csharp!
Response.ContentType = "text/html";
```
```csharp!
Response.AddHeader("X-CustomHeader", "Custom Value");
```
- 設定回應狀態:使用Response物件,可以設定回應的狀態碼和描述。例如,使用`Response.StatusCode`屬性可以設定回應的HTTP狀態碼,而`Response.StatusDescription`屬性可以設定狀態碼的描述。
```csharp!
Response.StatusDescription = "OK";
```
Response物件提供了豐富的功能,可用於控制伺服器對客戶端的回應,並根據需求設定回應內容、標頭和狀態等相關訊息。
### Request
:::info
Request物件是ASP.NET框架中的一個核心類別,**用於處理客戶端對伺服器的請求。**
:::
- **獲取請求資訊**:透過Request物件,可以獲取關於客戶端請求的各種資訊。例如,使用`Request.QueryString`屬性可以獲取請求的查詢字串參數,而`Request.Form`屬性則可以獲取POST請求中的表單參數。
```csharp!
string productId = Request.QueryString["id"];
```
- **獲取請求標頭**:Request物件提供了許多屬性和方法,用於獲取客戶端請求的標頭資訊。例如,使用`Request.Headers`屬性可以獲取所有的標頭,而`Request.UserAgent`屬性則可以獲取客戶端瀏覽器的用戶代理字串。
```csharp!
foreach (string headerKey in Request.Headers.Keys)
{
string headerValue = Request.Headers[headerKey];
Console.WriteLine($"{headerKey}: {headerValue}");
}
```
- **處理Cookie**:使用Request物件,可以方便地處理客戶端發送的Cookie。例如,使用`Request.Cookies`屬性可以獲取所有的Cookie集合,而`Request.Cookies["cookieName"]`則可以獲取特定的Cookie。
```csharp!
HttpCookie myCookie = Request.Cookies["myCookie"];
if (myCookie != null)
{
string cookieValue = myCookie.Value;
}
```
Request物件提供了豐富的功能,可用於獲取客戶端請求的各種資訊、處理標頭和Cookie等相關操作。
## 補充:什麼是物件(Object)什麼是類別(Class)差異在哪?
  這部分與**物件導向(Object Oriented Programming,OOP)** 相關
### 類別(Class)
:::info
  類別就是建構物件的設計藍圖,用來定義這些物件的屬性與方法,而物件則是根據這個藍圖實體化(Instantiation)後的個體。
:::
以車子作為舉例,我設置了一個Car的類別,其中定義了車子的顏色與品牌,在這邊Class就像是藍圖一樣
```csharp!
public class Car
{
public string color; // 車輛的顏色屬性
public string brand; // 車輛的品牌屬性
}
```
接著我實例化(new),產生Car這個物件
```csharp!
public class Car
{
public string color; // 車輛的顏色屬性
public string brand; // 車輛的品牌屬性
// 方法:啟動車輛
public void Start()
{
Console.WriteLine($"The {brand} car with {color} color is starting.");
// 在這裡可以實現啟動車輛的相應邏輯
}
}
```
### 物件(Object)
:::info
  而物件(Object)則是經由類別進行實例後所產生的東西
物件可以視為創建物件的模型,它定義了物件的特性(屬性Properties)和行為(方法 Method)
:::
  以"人"作為舉例,這個類別可以包含屬性(例如姓名、年齡)和方法(例如說話、走路)。
* 方法(method)
**物件的行為**,對物件的**動態描述**。
Console.WriteLine(“Hello World!”)為例,WriteLine是Console的其中一個方法,Hello World!是參數,以車子的例子來說"啟動車子"就是他的行為這邊用 `myCar.Start()`來呼叫他
* 屬性(Properties)
對於物件的一種**靜態描述**也就是他的一些特徵。
像是上面的Car的類別中就定義了Car的顏色&品牌
```csharp!
Car myCar = new Car(); // 創建 Car 物件的實例
myCar.color = "Red"; // 設定車輛的顏色屬性為 "Red"
myCar.brand = "Toyota"; // 設定車輛的品牌屬性為 "Toyota"
myCar.Start(); // 呼叫車輛的啟動方法
```