由 Tom FitzMacken 撰寫
本文將介紹使用 Razor 語法 ASP.NET 網頁的程式設計。 ASP.NET 是 Microsoft 用於在網頁伺服器上運行動態網頁的技術。 本文重點介紹如何使用 C# 程式語言。
您將學到的內容:
- 使用 Razor 語法開始 ASP.NET 網頁程式設計的八大建議。
- 你需要掌握基本的程式設計概念。
- ASP.NET 伺服器程式碼和 Razor 語法到底是關於什麼。
軟體版本
- ASP.NET 網頁(Razor)3
此教學同時適用於 ASP.NET Web Pages 2。
八大程式設計技巧
本節列出幾個你在開始使用 Razor 語法撰寫伺服器程式碼時 ASP.NET 絕對需要知道的技巧。
備註
Razor 語法基於 C# 程式語言,而 C# 是 ASP.NET 網頁中最常用的語言。 不過 Razor 語法也支援 Visual Basic 語言,你看到的所有操作也可以在 Visual Basic 裡做。 詳情請參閱附錄 《Visual Basic 語言與語法》。
你可以在文章後面找到更多關於這些程式設計技術的細節。
1. 你用 @ 字元在頁面上加入程式碼
@字元開始於串聯表達式、單語句區塊和多語句區塊:
<!-- Single statement blocks -->
@{ var total = 7; }
@{ var myMessage = "Hello World"; }
<!-- Inline expressions -->
<p>The value of your account is: @total </p>
<p>The value of myMessage is: @myMessage</p>
<!-- Multi-statement block -->
@{
var greeting = "Welcome to our site!";
var weekDay = DateTime.Now.DayOfWeek;
var greetingMessage = greeting + " Today is: " + weekDay;
}
<p>The greeting is: @greetingMessage</p>
以下是網頁在瀏覽器執行時的樣貌:
小提示
HTML 編碼
當你在頁面中用字 @ 元顯示內容時,就像前面的例子一樣,ASP.NET HTML 編碼輸出。 這會用程式碼取代保留的 HTML 字元(如 < 和 >& ),使字元能在網頁中顯示為字元,而非被解讀為 HTML 標籤或實體。 若沒有 HTML 編碼,伺服器程式碼的輸出可能無法正確顯示,並可能讓頁面暴露在安全風險之中。
如果你的目標是輸出能將標籤呈現為標記的 HTML 標記(例如段落或<p></p>強調文字),請參考本文後面的「<em></em>」章節。
你可以在 《Working with Forms》中閱讀更多關於 HTML 編碼的資訊。
2. 你用大括號包住代碼區塊
一個 代碼區塊 包含一個或多個代碼陳述句,並以大括號包覆。
<!-- Single statement block. -->
@{ var theMonth = DateTime.Now.Month; }
<p>The numeric value of the current month: @theMonth</p>
<!-- Multi-statement block. -->
@{
var outsideTemp = 79;
var weatherMessage = "Hello, it is " + outsideTemp + " degrees.";
}
<p>Today's weather: @weatherMessage</p>
結果顯示在瀏覽器中:
3. 在區塊內,每個代碼語句結尾都加分號
在一個代碼區塊內,每個完整的代碼語句必須以分號結尾。 內嵌表達式不會以分號結尾。
<!-- Single-statement block -->
@{ var theMonth = DateTime.Now.Month; }
<!-- Multi-statement block -->
@{
var outsideTemp = 79;
var weatherMessage = "Hello, it is " + outsideTemp + " degrees.";
}
<!-- Inline expression, so no semicolon -->
<p>Today's weather: @weatherMessage</p>
4. 你用變數來儲存數值
你可以把數值儲存在 變數裡,包括字串、數字、日期等等。你用關鍵字建立一個新變數 var 。 你可以直接在 @頁面中插入變數值。
<!-- Storing a string -->
@{ var welcomeMessage = "Welcome, new members!"; }
<p>@welcomeMessage</p>
<!-- Storing a date -->
@{ var year = DateTime.Now.Year; }
<!-- Displaying a variable -->
<p>Welcome to our new members who joined in @year!</p>
結果顯示在瀏覽器中:
5. 你用雙引號包住字串的數值
字串是一串被當作文字處理的字元序列。 要指定字串,你用雙引號包住它:
@{ var myString = "This is a string literal"; }
如果你想顯示的字串包含反斜線字元( \ )或雙引號( " ),請使用帶有運算子前綴的@ (在 C# 中,除非你使用逐字串,否則 \ 字元具有特殊意義。)
<!-- Embedding a backslash in a string -->
@{ var myFilePath = @"C:\MyFolder\"; }
<p>The path is: @myFilePath</p>
要嵌入雙引號,請使用逐字字串字面值並重複引號:
<!-- Embedding double quotation marks in a string -->
@{ var myQuote = @"The person said: ""Hello, today is Monday."""; }
<p>@myQuote</p>
以下是在頁面中使用這兩個例子的結果:
備註
請注意,這個 @ 字元同時用於 C# 中的逐字字串字面值標記,也用於標記 ASP.NET 頁中的程式碼。
6. 代碼以大小寫為區分
在 C# 中,關鍵字(如 var、 true和 if)和變數名稱是區分大小寫的。 以下程式碼行會產生兩個不同的變數, lastName 且 LastName.
@{
var lastName = "Smith";
var LastName = "Jones";
}
如果你宣告一個變數為 var lastName = "Smith"; ,並嘗試在頁面中引用該變數為 @LastName,你會得到的值 "Jones" 是 ,而不是 "Smith"。
備註
在 Visual Basic 中,關鍵字和變數 不 區分大小寫。
7. 你的程式碼大多涉及物件
物件代表你可以用來編程的東西——頁面、文字框、檔案、圖片、網頁請求、電子郵件、客戶紀錄(資料庫列)等等。物件有描述其特性的屬性,你可以讀取或更改——文字框物件有Text屬性(還有其他屬性)、請求物件有Url屬性、電子郵件有From屬性,客戶物件也有FirstName屬性。 物件也有它們能執行的「動詞」方法。 範例包括檔案物件 Save 的方法、影像物件 Rotate 的方法,以及電子郵件物件的方法 Send 。
你經常會處理這個 Request 物件,它會提供像是頁面文字框(表單欄位)的值、請求的瀏覽器類型、頁面網址、使用者身份等資訊。以下範例說明如何存取物件的 Request 屬性,以及如何呼叫 MapPath 物件的方法 Request ,該方法會給你伺服器上頁面的絕對路徑:
<table border="1">
<tr>
<td>Requested URL</td>
<td>Relative Path</td>
<td>Full Path</td>
<td>HTTP Request Type</td>
</tr>
<tr>
<td>@Request.Url</td>
<td>@Request.FilePath</td>
<td>@Request.MapPath(Request.FilePath)</td>
<td>@Request.RequestType</td>
</tr>
</table>
結果顯示在瀏覽器中:
8. 你可以寫出做出決策的程式碼
動態網頁的一個關鍵特色是你可以根據條件決定該怎麼做。 最常見的方法是使用 陳述 if 句(以及可選 else 陳述句)。
@{
var result = "";
if(IsPost)
{
result = "This page was posted using the Submit button.";
}
else
{
result = "This was the first request for this page.";
}
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<form method="POST" action="" >
<input type="Submit" name="Submit" value="Submit"/>
<p>@result</p>
</form>
</body>
</html>
if(IsPost) 是 if(IsPost == true) 的簡寫形式。 除了 if 語句外,還有多種方法來測試條件、重複程式碼區塊等,這些將在本文後面詳細說明。
點擊 提交後,瀏覽器中顯示的結果如下:
小提示
HTTP GET 與 POST 方法,以及 IsPost 屬性
網頁(HTTP)所使用的協定支援非常有限數量的方法(動詞)用來向伺服器發出請求。 最常見的兩種是 GET,用於閱讀頁面,以及 POST,用於提交頁面。 一般來說,使用者第一次請求頁面時,會使用 GET 來請求該頁面。 如果使用者填寫表單後點擊提交按鈕,瀏覽器會向伺服器發送 POST 請求。
在網頁程式設計中,知道頁面是被請求為 GET 還是 POST 通常很有用,這樣你才能知道如何處理該頁面。 在 ASP.NET 網頁中,你可以使用該 IsPost 屬性來判斷請求是 GET 還是 POST。 如果請求是 POST,屬性 IsPost 會回傳 true,你可以做像是讀取表單文字框值這類操作。 你會看到許多範例,說明如何根據 的 IsPost值不同地處理頁面。
一個簡單的程式碼範例
這個過程會教你如何建立一個說明基本程式技術的頁面。 在這個例子中,你建立一個頁面讓使用者輸入兩個數字,然後它會將兩個數字加入並顯示結果。
在編輯器中建立一個新檔案,命名 為 AddNumbers.cshtml。
將以下程式碼和標記複製到頁面中,替換頁面中已有的內容。
@{ var total = 0; var totalMessage = ""; if(IsPost) { // Retrieve the numbers that the user entered. var num1 = Request["text1"]; var num2 = Request["text2"]; // Convert the entered strings into integers numbers and add. total = num1.AsInt() + num2.AsInt(); totalMessage = "Total = " + total; } } <!DOCTYPE html> <html lang="en"> <head> <title>Add Numbers</title> <meta charset="utf-8" /> <style type="text/css"> body {background-color: beige; font-family: Verdana, Arial; margin: 50px; } form {padding: 10px; border-style: solid; width: 250px;} </style> </head> <body> <p>Enter two whole numbers and then click <strong>Add</strong>.</p> <form action="" method="post"> <p><label for="text1">First Number:</label> <input type="text" name="text1" /> </p> <p><label for="text2">Second Number:</label> <input type="text" name="text2" /> </p> <p><input type="submit" value="Add" /></p> </form> <p>@totalMessage</p> </body> </html>以下是一些你要注意的事項:
- 字
@元會開始頁面中第一個程式碼區塊,並且它位於totalMessage頁面底部附近嵌入的變數之前。 - 頁面頂端的區塊被括號包圍。
- 在頂端的區塊中,所有行以分號結尾。
- 變數
total、num1、num2、totalMessage儲存數值及一串字串。 - 賦予
totalMessage變數的字串值以雙引號標示。 - 由於程式碼是區分大小寫的,當
totalMessage變數出現在頁面底部時,其名稱必須與頂端的變數完全一致。 - 這個表達式
num1.AsInt() + num2.AsInt()展示了如何操作物件和方法。 每個變數的方法AsInt會將使用者輸入的字串轉換成一個數字(整數),讓你能對它進行算術運算。 - 標籤
<form>包含屬性method="post"。 此規定當使用者點擊 新增時,頁面會透過 HTTP POST 方法傳送至伺服器。 當頁面提交時,if(IsPost)測試會被評估為 true,條件程式碼會執行,顯示加總數字的結果。
- 字
儲存頁面並在瀏覽器中執行。 (執行前請確定該頁面已在 檔案 工作區中被選取。)輸入兩個整數,然後點擊 新增 按鈕。
基本程式設計概念
本文將為你介紹 ASP.NET 網頁程式設計。 這不是一份完整的考試,只是快速介紹你最常用的程式設計概念。 即便如此,它幾乎涵蓋了你開始使用 ASP.NET 網頁所需的一切。
但首先,先說點技術背景。
Razor 語法、伺服器程式碼與 ASP.NET
Razor 語法是一種簡單的程式設計語法,用於將伺服器端程式碼嵌入網頁中。 在使用 Razor 語法的網頁中,內容分為兩種:客戶端內容與伺服器程式碼。 客戶端內容是指你在網頁上習慣看到的東西:HTML 標記(元素)、樣式資訊(如 CSS)、可能的客戶端腳本如 JavaScript,以及純文字。
Razor 語法允許你將伺服器程式碼加入客戶端內容。 如果頁面中有伺服器程式碼,伺服器會先執行該程式碼,然後才會將頁面送回瀏覽器。 透過在伺服器端執行,程式碼能執行單靠客戶端內容較複雜的任務,例如存取伺服器端資料庫。 最重要的是,伺服器程式碼能動態產生客戶端內容——它可以即時產生 HTML 標記或其他內容,然後連同頁面中可能包含的任何靜態 HTML 一起傳送到瀏覽器。 從瀏覽器的角度來看,伺服器程式碼產生的客戶端內容和其他客戶端內容沒什麼不同。 如你所見,所需的伺服器程式碼相當簡單。
包含 Razor 語法的 ASP.NET 網頁會有特殊的副檔名(.cshtml 或 .vbhtml)。 伺服器會辨識這些擴充功能,執行帶有 Razor 語法標記的程式碼,然後將頁面傳送到瀏覽器。
ASP.NET 在哪個部分扮演角色?
Razor 語法基於Microsoft一項名為 ASP.NET 的技術,而 又是基於 Microsoft .NET Framework 的。 The.NET Framework 是 Microsoft 提供的大型且全面的程式設計框架,幾乎適用於開發任何類型的電腦應用程式。 ASP.NET 是 .NET Framework 中專門為建立網頁應用程式設計的部分。 開發者利用 ASP.NET 打造了世界上許多最大且流量最高的網站。 (只要你在網站的網址中看到副檔名 .aspx ,就知道該網站是用 ASP.NET 來撰寫的。)
Razor 語法讓你擁有 ASP.NET 的全部功能,但用的是簡化語法,對初學者來說更容易學,對專家來說也更高效。 雖然這種語法簡單易用,但它與 ASP.NET 及 .NET Framework 的親戚關係,意味著隨著網站越來越複雜,你就能利用更大型框架的力量。
小提示
類別與實例
ASP.NET 伺服器程式碼使用物件,而物件又建立在類別的概念之上。 類別是物件的定義或範本。 例如,應用程式可能包含 Customer 一個類別,定義任何客戶物件所需的屬性與方法。
當應用程式需要處理實際的顧客資訊時,它會建立(或 實例化)一個顧客物件。 每個個別客戶都是該 Customer 類別的獨立實例。 每個實例支援相同的屬性和方法,但每個實例的屬性值通常不同,因為每個客戶物件都是獨一無二的。 在一個客戶物件中,該 LastName 物件可能是「Smith」;在另一個客戶物件中,該 LastName 物件可能是「Jones」。
同樣地,你網站上的任何一個網頁都是 Page 該類別的 Page 物件。 頁面上的按鈕是 Button 該類別的物件 Button ,依此類推。 每個實例都有其獨特的特性,但它們都是基於物件類別定義中所指定的。
基本語法
你之前看到了一個基本範例,教你如何建立 ASP.NET 網頁頁面,以及如何將伺服器程式碼加入 HTML 標記。 在這裡,你將學習使用 Razor 語法撰寫 ASP.NET 伺服器程式碼的基礎——也就是程式語言的規則。
如果你有程式設計經驗(尤其是你用過 C、C++、C#、Visual Basic 或 JavaScript),這裡讀到的內容應該會很熟悉。 你大概只需要熟悉如何將伺服器代碼加入到 .cshtml 檔案的標記中。
在程式碼區塊中結合文字、標記與程式碼
在伺服器程式碼區塊中,你通常想輸出文字或標記(或兩者皆有)到頁面。 如果伺服器程式碼區塊包含非程式碼的文字,應該直接渲染,ASP.NET 需要能區分該文字與程式碼。 有幾種方法可以做到這一點。
將文字包圍在例如
<p></p>或<em></em>這樣的 HTML 元素中:@if(IsPost) { // This line has all content between matched <p> tags. <p>Hello, the time is @DateTime.Now and this page is a postback!</p> } else { // All content between matched tags, followed by server code. <p>Hello <em>stranger</em>, today is: <br /> </p> @DateTime.Now }HTML 元素可以包含文字、額外 HTML 元素以及伺服器程式碼表達式。 當 ASP.NET 看到開啟的 HTML 標籤(例如
<p>),它會將所有內容包括元素及其內容都照原樣呈現給瀏覽器,並邊做邊解析伺服器程式碼表達式。使用
@:運算子或<text>元素。 輸出@:一行內容,包含純文字或未匹配的 HTML 標籤;<text>該元素會包圍多行以輸出。 當你不想將 HTML 元素渲染成輸出時,這些選項非常有用。@if(IsPost) { // Plain text followed by an unmatched HTML tag and server code. @: The time is: <br /> @DateTime.Now <br/> // Server code and then plain text, matched tags, and more text. @DateTime.Now @:is the <em>current</em> time. }如果你想輸出多行文字或未匹配的 HTML 標籤,可以在每行前加上
@:,或是將該行包圍在元素<text>中。 與操作@:符類似,<text>標籤由 ASP.NET 用來識別文字內容,且不會在頁面輸出中呈現。@if(IsPost) { // Repeat the previous example, but use <text> tags. <text> The time is: <br /> @DateTime.Now <br/> @DateTime.Now is the <em>current</em> time. </text> } @{ var minTemp = 75; <text>It is the month of @DateTime.Now.ToString("MMMM"), and it's a <em>great</em> day! <br /><p>You can go swimming if it's at least @minTemp degrees. </p></text> }第一個範例重複前一個範例,但使用一對
<text>標籤包圍文字以供渲染。 在第二個範例中,<text>and</text>標籤包含三行,這些行皆包含部分未包含的文字及未匹配的 HTML 標籤(<br />),以及伺服器程式碼與匹配的 HTML 標籤。 此外,你也可以在每行前面個別加上@:運算子;這兩種方式都可以。備註
當您按照本節所示使用 HTML 元素、
@:運算子或<text>元素輸出文字時,ASP.NET 不會將輸出內容進行 HTML 編碼。 (如前所述,ASP.NET 會編碼伺服器程式碼表達式與前置@程式碼區塊的輸出,除非在本節特別說明。)
空白
陳述中多餘的空格(以及字串文字外)不會影響陳述:
@{ var lastName = "Smith"; }
語句中的換行不會影響語句本身,而且你可以包裝語句以提升閱讀性。 以下陳述相同:
@{ var theName =
"Smith"; }
@{
var
personName
=
"Smith"
;
}
然而,你不能在字串中間繞行一條線。 下列範例無法運作:
@{ var test = "This is a long
string"; } // Does not work!
要將像上述程式碼那樣繞行成多行的長字串結合,有兩個選項。 你可以使用串接運算子(+),你稍後會在本文中看到。 你也可以用這個 @ 字元來建立逐字字串的字面值,就像你在本文前面看到的那樣。 你可以逐字斷開字串字面值:
@{ var longString = @"This is a
long
string";
}
程式碼(及標記)註解
留言讓你可以為自己或他人留下留言。 它們也允許你停用(註解掉)一段程式碼或標記,這段程式碼或標記你不想執行但暫時想保留在頁面上。
Razor 程式碼和 HTML 標記的註解語法是不同的。 與所有 Razor 程式碼一樣,Razor 註解會在伺服器上處理(然後移除)後,頁面才會被送入瀏覽器。 因此,Razor 註解語法允許你在程式碼(甚至標記)中放入註解,編輯檔案時能看到,但使用者甚至在頁面原始碼中都看不到。
對於 ASP.NET Razor 註解,請以 @* 開始,並以 *@ 結束。 評論可以是一行,也可以是多行:
@* A one-line code comment. *@
@*
This is a multiline code comment.
It can continue for any number of lines.
*@
這是程式碼區塊中的一個註解:
@{
@* This is a comment. *@
var theVar = 17;
}
這是同一段程式碼,但那一行程式碼被註解掉,無法執行:
@{
@* This is a comment. *@
@* var theVar = 17; *@
}
在程式碼區塊內,作為使用 Razor 註解語法的替代方案,你可以使用你所使用的程式語言的註解語法,例如 C#:
@{
// This is a comment.
var myVar = 17;
/* This is a multi-line comment
that uses C# commenting syntax. */
}
在 C# 中,單行註解前會加上字元 // ,多行註解則以 開頭 /* 並以 結尾 */。 (與 Razor 留言相同,C# 留言不會被渲染到瀏覽器。)
關於標記,你可能知道,可以建立一個 HTML 註解:
<!-- This is a comment. -->
HTML 註解以 `<!--` 字元開頭,以 `-->` 字元結尾。 你可以用 HTML 註解包圍文字,也可以包圍任何你想保留但不想渲染的 HTML 標記。 此 HTML 註解將隱藏標籤及其文字的全部內容:
<!-- <p>This is my paragraph.</p> -->
與 Razor 註解不同,HTML 留言 會 渲染到頁面,使用者可透過查看頁面原始碼來查看。
Razor 對巢狀的 C# 區塊有限制。 更多資訊請參閱「命名的 C# 變數與巢狀區塊產生壞掉的程式碼」
變數
變數是一個命名的物件,用來儲存資料。 你可以為變數命名任何東西,但名稱必須以字母字元開頭,且不能包含空白或保留字元。
變數與資料型態
變數可以有特定的資料型別,該型態指示變數中儲存的資料種類。 你可以有字串變數儲存字串值(像是「Hello world」)、整數變數儲存整數值(像是 3 或 79),以及日期變數用來儲存各種格式的日期值(例如 4/12/2012 或 March 2009)。 而且還有很多其他資料型態可以使用。
不過,通常你不需要為變數指定類型。 大多數時候,ASP.NET 可以根據變數資料的使用方式來判斷類型。 (有時你必須指定一個類型,你會看到這種情況的例子。)
你可以用 var 關鍵字宣告變數(如果你不想指定型別),或者用型別名稱來宣告變數:
@{
// Assigning a string to a variable.
var greeting = "Welcome!";
// Assigning a number to a variable.
var theCount = 3;
// Assigning an expression to a variable.
var monthlyTotal = theCount + 5;
// Assigning a date value to a variable.
var today = DateTime.Today;
// Assigning the current page's URL to a variable.
var myPath = this.Request.Url;
// Declaring variables using explicit data types.
string name = "Joe";
int count = 5;
DateTime tomorrow = DateTime.Now.AddDays(1);
}
以下範例展示了網頁中變數的一些典型用途:
@{
// Embedding the value of a variable into HTML markup.
<p>@greeting, friends!</p>
// Using variables as part of an inline expression.
<p>The predicted annual total is: @( monthlyTotal * 12)</p>
// Displaying the page URL with a variable.
<p>The URL to this page is: @myPath</p>
}
如果你將前面的例子合併在頁面中,你會在瀏覽器中看到以下畫面:
資料型態轉換與測試
雖然 ASP.NET 通常能自動判斷資料型態,但有時無法。 因此,你可能需要透過進行明確的轉換來幫助 ASP.NET。 即使你不需要轉換類型,有時候測試看看你可能處理的資料類型會很有幫助。
最常見的情況是你必須將字串轉換成其他類型,例如整數或日期。 以下範例展示了一個典型情況,必須將字串轉換成數字。
@{
var total = 0;
if(IsPost) {
// Retrieve the numbers that the user entered.
var num1 = Request["text1"];
var num2 = Request["text2"];
// Convert the entered strings into integers numbers and add.
total = num1.AsInt() + num2.AsInt();
}
}
一般來說,使用者輸入會以串聯的形式呈現給你。 即使你已要求使用者輸入數字,即使他們輸入了一個數字,當使用者送出輸入並且您在程式碼中讀取時,資料仍然是字串格式。 因此,你必須將字串轉換成一個數字。 在範例中,如果你嘗試對這些值進行算術而不轉換,會導致以下錯誤,因為 ASP.NET 無法加兩串字串:
無法隱式地將型別 'string' 轉換成 'int'。
要將數值轉換成整數,你就呼叫這個 AsInt 方法。 如果轉換成功,你就可以將數字相加。
下表列出了一些常見的變數轉換與測試方法。
方法
說明
範例
AsInt(), IsInt()
將代表整數(例如「593」)的字串轉換為整數。
var myIntNumber = 0;
var myStringNum = "539";
if(myStringNum.IsInt()==true){
myIntNumber = myStringNum.AsInt();
}
AsBool(), IsBool()
將像「true」或「false」這樣的字串轉換成布林型態。
var myStringBool = "True";
var myVar = myStringBool.AsBool();
AsFloat(), IsFloat()
將像「1.3」或「7.439」這類小數值的字串轉換成浮點數。
var myStringFloat = "41.432895";
var myFloatNum = myStringFloat.AsFloat();
AsDecimal(), IsDecimal()
將像「1.3」或「7.439」這類小數值的字串轉換成十進位數。 (在 ASP.NET 中,十進位數比浮點數更精確。)
var myStringDec = "10317.425";
var myDecNum = myStringDec.AsDecimal();
AsDateTime(), IsDateTime()
將代表日期與時間值的字串轉換為 ASP.NET DateTime 型別。
var myDateString = "12/27/2012";
var newDate = myDateString.AsDateTime();
ToString()
將任何其他資料型態轉換成字串。
int num1 = 17;
int num2 = 76;
// myString is set to 1776
string myString = num1.ToString() +
num2.ToString();
操作員
運算子是一個關鍵字或字元,用來告訴 ASP.NET 在表達式中要執行哪種指令。 C# 語言(以及基於它的 Razor 語法)支援許多運算子,但你只需要辨識幾個就能開始。 下表總結了最常見的運算子。
運算子
說明
Examples
+
-
*
/
數值表達式中使用的數學運算子。
@(5 + 13)
@{ var netWorth = 150000; }
@{ var newTotal = netWorth * 2; }
@(newTotal / 2)
=
任務。 將陳述右側的值指派給左側物件。
var age = 17;
==
平等。 若兩者值相等,則回傳 true 。 請注意=運算子與==運算子之間的區別。
var myNum = 15;
if (myNum == 15) {
// Do something.
}
!=
不平等。 若兩者不相等,則返回 true。
var theNum = 13;
if (theNum != 15) {
// Do something.
}
< > <= >=
小於、大於、小於或等於、大於或等於。
if (2 < 3) {
// Do something.
}
var currentCount = 12;
if(currentCount >= 12) {
// Do something.
}
+
串接,用於連接字串。 ASP.NET 根據表達式的資料型態,知道此運算子與加法運算子的差異。
// The displayed result is "abcdef".
@("abc" + "def")
+=
-=
增量運算子與減量運算子,分別對變數加1和減1。
int theCount = 0;
theCount += 1; // Adds 1 to count
.
點。 用來區分物件及其屬性和方法。
var myUrl = Request.Url;
var count = Request["Count"].AsInt();
()
括號。 用於分組表達式及傳遞參數給方法。
@(3 + 7)
@Request.MapPath(Request.FilePath);
[]
括號。 用於存取陣列或集合中的值。
var income = Request["AnnualIncome"];
!
不。 將 true 值轉換為 false,反之亦然。 通常用作簡寫方式來測試false(即不是true)。
bool taskCompleted = false;
// Processing.
if(!taskCompleted) {
// Continue processing
}
&&
||
邏輯 AND 與 OR 用於連結條件。
bool myTaskCompleted = false;
int totalCount = 0;
// Processing.
if(!myTaskCompleted && totalCount < 12) {
// Continue processing.
}
程式碼中處理檔案與資料夾路徑
你經常會在程式碼中處理檔案和資料夾路徑。 以下是網站實體資料夾結構的範例,可能出現在您的開發電腦上:
C:\WebSites\MyWebSite default.cshtml datafile.txt \images Logo.jpg \styles Styles.css
以下是關於網址與路徑的一些重要細節:
- URL 以網域名稱()
http://www.example.com或伺服器名稱(http://localhost,http://mycomputer)開頭。 - URL 對應主機電腦上的實體路徑。 例如,
http://myserver可能對應伺服器上的資料夾 C:\websites\mywebsite 。 - 虛擬路徑是程式碼中用來表示路徑的簡寫,無需指定完整路徑。 它包含網址中緊接網域或伺服器名稱的部分。 使用虛擬路徑時,你可以將程式碼移到不同的網域或伺服器,而不必更新路徑。
這裡有一個例子,幫助你理解兩者的差異:
| 完整網址 | http://mycompanyserver/humanresources/CompanyPolicy.htm |
|---|---|
| 伺服器名稱 | mycompanyserver |
| 虛擬路徑 | /人力資源/CompanyPolicy.htm |
| 物理路徑 | C:\mywebsites\humanresources\CompanyPolicy.htm |
虛擬根節點是 /,就像你的 C 磁碟機根節點是 。 (虛擬資料夾路徑總是使用斜線。)資料夾的虛擬路徑不必與實體資料夾名稱相同;也可以是別名。 (在生產伺服器上,虛擬路徑很少與實體路徑完全匹配。)
當你在程式碼中處理檔案和資料夾時,有時需要參考實體路徑,有時則需要參考虛擬路徑,視你處理的物件而定。 ASP.NET 提供了這些工具來在程式碼中處理檔案和資料夾路徑:Server.MapPath 方法、~ 運算子及 Href 方法。
虛擬路徑轉換為實體路徑:Server.MapPath 方法
這個 Server.MapPath 方法會將虛擬路徑(例如 /default.cshtml)轉換成絕對的實體路徑(例如 C:\WebSites\MyWebSiteFolder\default.cshtml)。 當你需要完整的實體路徑時,你都會用這個方法。 一個典型的例子是在網頁伺服器上閱讀或寫入文字檔或圖片檔時。
你通常不知道你網站在主機伺服器上的絕對物理路徑,因此此方法可以將你已知的路徑——虛擬路徑——轉換成伺服器上的對應路徑。 你將虛擬路徑傳給檔案或資料夾,方法會回傳實體路徑:
@{
var dataFilePath = "~/dataFile.txt";
}
<!-- Displays a physical path C:\Websites\MyWebSite\datafile.txt -->
<p>@Server.MapPath(dataFilePath)</p>
引用虛擬根:~ 運算子與 Href 方法
在 .cshtml 或 .vbhtml 檔案中,你可以用 ~ 運算子參考虛擬根路徑。 這非常方便,因為你可以在網站上移動頁面,且它們包含的連結不會被破壞。 如果你將網站搬到其他地點,這也非常實用。 以下是一些範例:
@{
var myImagesFolder = "~/images";
var myStyleSheet = "~/styles/StyleSheet.css";
}
如果網站是 http://myserver/myapp,ASP.NET 在頁面運行時會如何處理這些路徑:
-
myImagesFolder:http://myserver/myapp/images -
myStyleSheet:http://myserver/myapp/styles/Stylesheet.css
(你實際上不會看到這些路徑是變數的值,但 ASP.NET 會把路徑當作變數值來處理。)
你可以在伺服器程式碼(如上)和標記中使用這個 ~ 運算子,就像這樣:
<!-- Examples of using the ~ operator in markup in ASP.NET Web Pages -->
<a href="~/Default">Home</a>
<img src="~/images/MyImages.png" />
在標記中,你可以使用 ~ 操作符來建立指向資源的路徑,例如圖片檔案、其他網頁和 CSS 檔案。 當頁面執行時,ASP.NET 會瀏覽頁面(包含程式碼與標記),並解析所有 ~ 指向適當路徑的參考。
條件邏輯與迴圈
ASP.NET 伺服器程式碼允許你根據條件執行任務,並撰寫重複特定次數語句的程式碼(也就是執行迴圈的程式碼)。
測試條件
要測試一個簡單條件,你會使用 這個 if 陳述,根據你指定的測試,該陳述會回傳真或假:
@{
var showToday = true;
if(showToday)
{
@DateTime.Today;
}
}
關鍵字 if 開始區塊。 實際測試(條件)置於括號內,會回傳真或假。 當測試為真時執行的語句會被括號包圍。 一個 if 陳述句可以包含 else 一個區塊,該區塊指定在條件為假時要執行的陳述句:
@{
var showToday = false;
if(showToday)
{
@DateTime.Today;
}
else
{
<text>Sorry!</text>
}
}
你可以用區 else if 塊加入多個條件:
@{
var theBalance = 4.99;
if(theBalance == 0)
{
<p>You have a zero balance.</p>
}
else if (theBalance > 0 && theBalance <= 5)
{
<p>Your balance of $@theBalance is very low.</p>
}
else
{
<p>Your balance is: $@theBalance</p>
}
}
在此範例中,若 if 區塊的第一個條件不為真,則檢查該 else if 條件。 若符合該條件,則執行區 else if 塊中的陳述。 若未符合任何條件,則執行區塊中的 else 語句。 你可以加入任意數量的 else if 區塊,然後以 else 區塊作為「其他所有」條件的結尾。
要測試大量條件,使用一個 switch 區塊:
@{
var weekday = "Wednesday";
var greeting = "";
switch(weekday)
{
case "Monday":
greeting = "Ok, it's a marvelous Monday";
break;
case "Tuesday":
greeting = "It's a tremendous Tuesday";
break;
case "Wednesday":
greeting = "Wild Wednesday is here!";
break;
default:
greeting = "It's some other day, oh well.";
break;
}
<p>Since it is @weekday, the message for today is: @greeting</p>
}
要測試的值以括號內標示(範例中為變 weekday 數)。 每個測試都使用一個以冒號 (:) 結尾的case語句。 如果語 case 句的值與測試值相符,該代碼區塊就會被執行。 你用一份 break 聲明來結尾每個案件陳述。 (如果你忘記在每個 case 區塊中加入 break,下一個 case 語句的程式碼也會執行。)一個 switch 區塊通常會在最後一個情況中包含一個 default 語句作為「所有其他」的選項,當其他情況都不成立時會執行。
瀏覽器中最後兩個條件區塊的結果如下:
迴圈程式碼
你經常需要反覆執行相同的語句。 你可以透過迴圈來實現這一點。 例如,你經常對資料集合中的每個項目執行相同的語句。 如果你確切知道要迴圈幾次,就可以使用for迴圈。 這種迴圈對於遞增或遞減計數特別有用:
@for(var i = 10; i < 21; i++)
{
<p>Line #: @i</p>
}
迴圈以 for 關鍵字開頭,接著三個括號內的陳述,每個陳述以分號結尾。
- 括號內的第一句話
var i=10;()建立一個計數器,並將其初始化為10。 你不必命名計數i器——你可以使用任何變數。 當迴for圈運行時,計數器會自動遞增。 - 第二個陳述
i < 21;設定要計算的距離條件。 在這種情況下,你希望它能達到最大 20(也就是說,在計數器低於 21 時繼續前進)。 - 第三句(
i++)使用遞增運算子,簡單地指定每次迴圈執行時,計數器應加1。
大括號內部是每次迴圈迭代都會執行的程式碼。 標記每次會產生一個新的段落(<p> 元素),並在輸出中加入一行,顯示( i 計數器)的值。 當你執行這個頁面時,範例會產生 11 行顯示輸出,每行的文字標示項目編號。
如果你在處理一個集合或陣列時,通常會使用 foreach 迴圈。 收藏是一組相似的物件,迴 foreach 圈讓你能對收藏中的每個項目執行任務。 這種迴圈對集合很方便,因為不像迴 for 圈,你不需要增加計數器或設定限制。 相反地, foreach 循環程式碼會直接在集合中持續進行直到完成。
例如,以下程式碼回傳集合中的 Request.ServerVariables 項目,集合是一個包含你網頁伺服器資訊的物件。 它使用 foreac h 迴圈來顯示每個項目名稱,方法是在 HTML 項目符號列表中建立新 <li> 元素。
<ul>
@foreach (var myItem in Request.ServerVariables)
{
<li>@myItem</li>
}
</ul>
關鍵字 foreach 後接著括號,其中宣告一個代表集合中單個項目的變數(例如:var item),然後是 in 關鍵字,接下來是要遍歷的集合。 在迴圈的主體 foreach 中,你可以使用你之前宣告的變數存取目前的項目。
若要建立更通用的迴圈,請使用以下 while 陳述:
@{
var countNum = 0;
while (countNum < 50)
{
countNum += 1;
<p>Line #@countNum: </p>
}
}
while迴圈以關鍵字while開始,後接括號,指定迴圈繼續條件是(此處為countNum小於 50),然後是要重複的區塊。 迴圈通常會增(加)或減(減)用於計數的變數或物件。 在這個例子中,每次迴圈運行時,+= 運算子都會將 countNum 加上 1。 (要在倒數迴圈中遞減變數,你會使用遞減運算子 -=)。
物品與收藏
ASP.NET 網站中的幾乎所有東西都是物件,包括網頁本身。 本節討論你在程式碼中會經常接觸到的一些重要物件。
頁面物件
ASP.NET 中最基本的物件是頁面。 你可以直接存取頁面物件的屬性,無需任何限定物件。 以下程式碼透過 Request 物件取得頁面的檔案路徑:
@{
var path = Request.FilePath;
}
為了清楚說明你參考的是目前頁面物件的屬性和方法,你可以選擇性地用關鍵字 this 來代表程式碼中的頁面物件。 以下是先前的程式碼範例,並 this 新增以表示該頁面:
@{
var path = this.Request.FilePath;
}
你可以利用物件的 Page 屬性來獲取大量資訊,例如:
Request。 如你所見,這是關於當前請求的資訊彙整,包括請求的瀏覽器類型、頁面網址、使用者身份等。Response。 這是一組關於回應(頁面)的資訊,當伺服器程式碼執行完成後,將傳送給瀏覽器。 例如,你可以利用這個特性將資訊寫入回應中。@{ // Access the page's Request object to retrieve the Url. var pageUrl = this.Request.Url; } <a href="@pageUrl">My page</a>
集合物件(陣列與字典)
集合是同一類型的物件集合,例如資料庫中的物件集合Customer。 ASP.NET 包含許多內建的集合,就像集合一樣 Request.Files 。
你經常會處理資料集合。 兩種常見的集合類型是 陣列 和 字典。 當你想儲存一組相似的項目,但又不想建立一個獨立變數來存放每個項目時,陣列非常有用:
@* Array block 1: Declaring a new array using braces. *@
@{
<h3>Team Members</h3>
string[] teamMembers = {"Matt", "Joanne", "Robert", "Nancy"};
foreach (var person in teamMembers)
{
<p>@person</p>
}
}
陣列則宣告特定的資料型別,例如 string、 int、 或 DateTime。 要表示變數可以包含陣列,請在宣告後加上括號(例如 string[] 或 int[])。 你可以透過陣列中的項目位置(索引)或使用 foreach 陳述句來存取。 陣列索引是基於零的——也就是說,第一個項目位於位置 0,第二個項目位於位置 1,依此類推。
@{
string[] teamMembers = {"Matt", "Joanne", "Robert", "Nancy"};
<p>The number of names in the teamMembers array: @teamMembers.Length </p>
<p>Robert is now in position: @Array.IndexOf(teamMembers, "Robert")</p>
<p>The array item at position 2 (zero-based) is @teamMembers[2]</p>
<h3>Current order of team members in the list</h3>
foreach (var name in teamMembers)
{
<p>@name</p>
}
<h3>Reversed order of team members in the list</h3>
Array.Reverse(teamMembers);
foreach (var reversedItem in teamMembers)
{
<p>@reversedItem</p>
}
}
你可以透過取得陣 Length 列的屬性來判斷一個陣列中項目的數量。 要取得特定項目在陣列中的位置(搜尋陣列),請使用該 Array.IndexOf 方法。 你也可以執行例如反轉陣列內容的Array.Reverse方法或排序內容的Array.Sort方法。
字串陣列程式碼在瀏覽器中顯示的輸出:
字典是一組鍵值對,你提供鍵(或名稱)來設定或取回對應的值:
@{
var myScores = new Dictionary<string, int>();
myScores.Add("test1", 71);
myScores.Add("test2", 82);
myScores.Add("test3", 100);
myScores.Add("test4", 59);
}
<p>My score on test 3 is: @myScores["test3"]%</p>
@{myScores["test4"] = 79;}
<p>My corrected score on test 4 is: @myScores["test4"]%</p>
要建立字典,你使用 new 關鍵字表示你正在建立一個新的字典物件。 你可以用 var 關鍵字將字典指派到變數上。 你用括號( ) < > 表示字典中項目的資料型態。 在聲明的結尾,你必須加上一對括號,因為這其實是一種建立新字典的方法。
要將項目加入字典,你可以呼叫 Add 字典變數的方法(myScores 此例為 ),然後指定鍵和值。 或者,你也可以用方括號標示鍵,並做簡單的指派,如下範例所示:
myScores["test4"] = 79;
要從字典取得一個數值,請在括號內指定金鑰:
var testScoreThree = myScores["test3"];
呼叫帶有參數的方法
正如你在本文前面所讀,你用來編程的物件可以有方法。 例如,一個 Database 物件可能有一種 Database.Connect 方法。 許多方法也包含一個或多個參數。
參數是你傳遞給方法的值,用以使該方法完成其任務。 例如,看看該 Request.MapPath 方法的宣告,包含三個參數:
public string MapPath(string virtualPath, string baseVirtualDir,
bool allowCrossAppMapping);
(這行經過折行以提高可讀性。記住,換行幾乎可以在任何地方進行,除了在用引號括起的字串內。)
此方法回傳伺服器上對應特定虛擬路徑的物理路徑。 該方法的三個參數為 virtualPath、 baseVirtualDir、 和 allowCrossAppMapping。 (請注意,在宣告中,參數列出了他們會接受的資料類型。)當你呼叫這個方法時,必須提供三個參數的數值。
Razor 語法提供兩種參數傳遞方式的選項: 位置參數 和 命名參數。 要用位置參數呼叫方法,你要依照方法宣告中指定的嚴格順序傳遞參數。 (通常你可以透過閱讀方法文件來知道這個順序。)你必須依照順序操作,且不能跳過任何參數——如有需要,會傳遞空字串()""或 null 是你沒有值的位置參數。
以下範例假設你網站上有一個名為 scripts 的資料夾。 程式碼會呼叫該 Request.MapPath 方法,並以正確的順序傳遞三個參數的值。 接著會顯示所產生的映射路徑。
@{
// Pass parameters to a method using positional parameters.
var myPathPositional = Request.MapPath("/scripts", "/", true);
}
<p>@myPathPositional</p>
當一個方法有很多參數時,你可以透過使用命名參數來讓程式碼更易讀。 要使用命名參數呼叫方法,先指定參數名稱,接著冒號(:),然後是值。 命名參數的優點是你可以以任何你想要的順序傳遞它們。 缺點是方法呼叫不夠簡潔。
以下範例使用與上述相同的方法,但使用命名參數來提供數值:
@{
// Pass parameters to a method using named parameters.
var myPathNamed = Request.MapPath(baseVirtualDir: "/",
allowCrossAppMapping: true, virtualPath: "/scripts");
}
<p>@myPathNamed</p>
如你所見,參數傳遞的順序不同。 不過,如果你執行前一個範例和這個範例,它們會回傳相同的值。
處理錯誤
Try-Catch 陳述
你的程式碼中常常會有某些陳述可能因你無法控制的原因而失敗。 例如:
- 如果你的程式碼嘗試建立或存取檔案,可能會發生各種錯誤。 你想要的檔案可能根本不存在、可能被鎖定、程式碼可能沒有權限等等。
- 同樣地,如果你的程式碼嘗試更新資料庫中的紀錄,可能會有權限問題,與資料庫的連線可能中斷,儲存的資料可能無效,等等。
在程式設計中,這些情況稱為 例外。 如果你的程式碼遇到例外,會產生(拋出)一個錯誤訊息,充其量只會讓使用者感到惱人:
在程式碼可能遇到例外的情況下,為了避免這類錯誤訊息,可以使用 try/catch 語句。 在陳述 try 句中,你執行你正在檢查的程式碼。 在一個或多個 catch 語句中,你可以尋找可能發生的特定錯誤(特定類型的例外)。 你可以包括任意數量的 catch 陳述,以尋找你預期的錯誤。
備註
我們建議你避免在陳述中使用此 Response.Redirect 方法 try/catch ,因為這可能導致頁面出現異常。
以下範例展示了一個頁面在第一次請求時建立文字檔,接著顯示一個按鈕讓使用者開啟該檔案。 這個範例故意使用錯誤的檔名,以引起異常。 程式碼包含 catch 兩種可能例外的語句: FileNotFoundException當檔名錯誤時會發生,以及 DirectoryNotFoundException當 ASP.NET 找不到資料夾時發生的例外。 (你可以在範例中將某個陳述取消註釋,以觀察當一切正常時其運作的狀況。)
如果你的程式碼沒處理這個例外,你會看到像前面截圖一樣的錯誤頁面。 不過,該 try/catch 區塊有助於防止使用者看到這類錯誤。
@{
var dataFilePath = "~/dataFile.txt";
var fileContents = "";
var physicalPath = Server.MapPath(dataFilePath);
var userMessage = "Hello world, the time is " + DateTime.Now;
var userErrMsg = "";
var errMsg = "";
if(IsPost)
{
// When the user clicks the "Open File" button and posts
// the page, try to open the created file for reading.
try {
// This code fails because of faulty path to the file.
fileContents = File.ReadAllText(@"c:\batafile.txt");
// This code works. To eliminate error on page,
// comment the above line of code and uncomment this one.
//fileContents = File.ReadAllText(physicalPath);
}
catch (FileNotFoundException ex) {
// You can use the exception object for debugging, logging, etc.
errMsg = ex.Message;
// Create a friendly error message for users.
userErrMsg = "A file could not be opened, please contact "
+ "your system administrator.";
}
catch (DirectoryNotFoundException ex) {
// Similar to previous exception.
errMsg = ex.Message;
userErrMsg = "A directory was not found, please contact "
+ "your system administrator.";
}
}
else
{
// The first time the page is requested, create the text file.
File.WriteAllText(physicalPath, userMessage);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Try-Catch Statements</title>
</head>
<body>
<form method="POST" action="" >
<input type="Submit" name="Submit" value="Open File"/>
</form>
<p>@fileContents</p>
<p>@userErrMsg</p>
</body>
</html>
其他資源
Visual Basic 程式設計
參考文件