Go to .NET Center USOL Vietnam
.NET Center
Ojima Ryoji and Nguyễn Huyền Nhung

Nhập môn ASP.NET 2.0

ASP.NET 2.0 là class library để tạo các Web application mà NET Framework 2.0 cung cấp. Trong phần nhập môn về ASP.NET 2.0 chúng tôi xin được giải thích về cấu trúc của ASP.NET 2.0 và những điểm cần lưu ý.

ASP.NET 2.0 có thể sinh các event từ post back, HTTP request và các control có thể hiển thị Web application bằng thẻ , bên cạnh đó cũng có thể phát triển bằng phương pháp "tương tự" với Visual Basic thông qua cấu trúc như maintain trạng thái. Tuy nhiên, có thể kết luận là nó "tương tự" chứ không hoàn toàn giống với Visual Basic. Vì vậy chúng ta cần phải chú ý là thông tin được ViewState maintain chỉ là control property, chú ý tới việc phải giảm sử dụng ViewState, và timing của các event khác nhau.

Ở đây chúng tôi xin được giải thích về cấu trúc Web application infrastructure mà ASP.NET 2.0 chạy trên đó, giải thích về cấu trúc của ASP.NET để thực hiện phương pháp phát triển tương tự với Visual Basic, đồng thời chúng tôi cũng xin được trình bày về những lỗ hổng có thể phát sinh do thực hiện phương pháp phát triển tương tự Visual Basic trên Web application.

Cấu trúc Web application

Trước tiên chúng tôi xin được trình bày về Web application infrastructure mà ASP.NET 2.0 chạy trên đó. Dưới đây là cấu trúc của Web application.

cấu trúc Web application

Web application được cấu tạo từ application server và Web browser. Business logic có trong tất cả các application server, Web browser chỉ đóng vai trò tiếp nhận input từ user và hiển thị màn hình. Ngoài ra, HTML (Hyper Text Markup Language) được dùng trong hiển thị màn hình theo Web browser, còn HTTP (Hyper Text Transfer Protocol) là protocol truyền tin giữa application web và web browser.

HTML là gì?

Chúng ta thử lấy ví dụ cụ thể về HTML. Dưới đây là HTML để hiển thị lên màn hình dòng "Hello, World!"

<html>
    <head>
        <title>HTML Sample</title>
    </head>
    <body>
        <h1>Hello, World!</h1>
    </body>
</html>

Trong HTML nội dung hiển thị được kiểm soát bằng thẻ có dạng thẻ mở <tên thẻ > và thẻ đóng </tên thẻ >. <html> trong ví dụ trên có nghĩa là tài liệu HTML, <head> là thẻ chứa thông tin chung về trang, <body> là phần chứa nội dung hiển thị. Ở ví dụ trên, do trong <body> dữ liệu dùng để kiểm soát có dòng chữ "Hello, World!" được bao bọc bằng thẻ mang ý nghĩa Heading Style 1 tức là <h1>, nên Web browser hiển thị dòng chữ "Hello, World!" với font và size tương ứng với Heading Style 1.

Cách tạo màn hình dùng để input data?

Màn hình dùng cho input dữ liệu biểu hiện bằng việc bao quanh các thẻ dùng cho input item như <input> và <select> bằng <form>. Chúng tôi xin được đưa ra ví dụ cụ thể như sau

<form action="next-page.aspx" method="get">
    <p>
        HonoricTitle:
        <select name="honorificTitleDropDownList">
            <option value="1" selected="selected">Mr.</option>
            <option value="2">Mrs.</option>
            <option value="3">Miss</option>
        </select>
    </p>
    <p>
        Name:
        <input type="text" name="nameTextBox" />
    </p>
    <p>
        <input type="submit" value="Send Data to Application Server" />
    </p>
</form>

<p> là thẻ để chỉ paragraph. <select> là drop down list, <input type="text"> là text box, <input type="submit"> là button. Ở HTML trên, ở trong thẻ <input> không có </input> là bởi vì trong trường hợp không có data hay thẻ khác trong đó thì có thể kết thúc phạm vi kiểm soát của thẻ bằng "/>". Ngoài ra, phần 'name="honoricTitleDropDownList"' trong thẻ là thuộc tính để kiểm soát thẻ . Ví dụ: Thuộc tính selected của <option> là item đã được lựa chọn default khi hiển thị màn hình.

Có nghĩa là khi thực hiện <form> bên trên thì sẽ được kết quả hiển thị như sau (Hãy click button. Trở thành error).


HonoricTitle:

Name:


Nếu muốn biết thêm?

Tất nhiên ngoài những cái đã nêu ra ở đây thì trong HTML còn có rất nhiều thẻ và thuộc tính khác (Nếu không như thế thì chắc chắn sẽ không tạo được nhiều Web site đa dạng và phong phú trong cuộc sống như vậy). Nếu bạn muốn tìm hiểu thêm về những thẻ và thuộc tính đó xin mời tham khảo ở MSDN library.

HTTP là gì?

HTTP là protocol truyền tin được dùng trong Web application. Đặc trưng là protocol đơn giản và phi trạng thái (stateless).

Đơn giản và phi trạng thái (stateless)?

Chúng ta hãy lấy ví dụ trong trường hợp khởi động Web browser, và nhập vào URL là "http://www.usol-v.com.vn/dotNETCenter/An_Introduction_of_ASP.NET_2.0/Default.htm". Khi đó, sẽ tạo request dựa vào HTTP như dưới đây và gửi thông tin (Lần này sử dụng Firefox 2.0).

GET /dotNETCenter/TechnicalDocuments/An_Introduction_of_ASP.NET_2.0/Default.htm HTTP/1.1
Host: www.usol-v.com.vn
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; ja; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

Phần quan trọng là dòng thứ nhất. Dòng thứ nhất này biểu thị việc sử dụng HTTP version 1.1 để get data được nhận biết bởi /dotNETCenter/TechnicalDocuments/An_Introduction_of_ASP.NET_2.0/Default.htm.

Dưới đây là response của application server đối với GET của HTTP ở trên (Trong application server có sử dụng IIS 6.0 trên Windows Server 2003).

HTTP/1.x 200 OK
Content-Length: 6736
Content-Type: text/html
Last-Modified: Mon, 10 Sep 2007 07:18:27 GMT
Accept-Ranges: bytes
Etag: "802bec87af3c71:221"
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Mon, 10 Sep 2007 08:01:25 GMT

<html>
    ...
</html>

Phần lược bỏ cuối cùng là HTML biểu thị nội dung của page. Cho dù là response của HTTP hay gì thì phần trọng yếu nhất vẫn là dòng thứ nhất. Dòng thứ nhất của response bên trên có nghĩa là sẽ căn cứ vào HTTP version 1.x, và stateless của nó sẽ là 200. 200 là mã mang ý nghĩa thành công, từ 300 đến 399 là thao tác cho browser như redirect, từ 400 đến 499 và từ 500 đến 599 nghĩa là có lỗi. Ví dụ, stateless trong trường hợp không tồn tại file tương ứng trong URL là 404, dòng đầu tiên của response đối với request đã chỉ ra URL của file không tồn tại sẽ như sau:

HTTP/1.x 404 Not Found

HTTP như đã trình bày, chính là protocol được cấu thành bằng các thao tác đơn giản với text base. Hơn nữa stateless đó thành công hay thất bại, thì trong HTTP, connection cũng sẽ bị ngắt ngay sau khi trả response đối với request. HTTP có đặc trưng là protocol truyền tin mang tính stateless, mỗi 1 request: request quá khứ, request hiện tại và request tương lai đều phải là 1 connection riêng biệt, và các request đó không có liên quan gì với nhau.

Trường hợp <form>

Trường hợp thuộc tính method trong <form> là "get" thì không có thay đổi nhiều so với nội dung gửi thông tin ở trường hợp trên. Và request trong trường hợp nhập "Mr." vào honorificTitleDropDownList của <form> mà đã giới thiệu trong phần "HTML là gì?" và nhập "Ojima" vào nameText sẽ như sau:

GET /TechnicalDocuments/An_Introduction_of_ASP.NET_2.0/next-page.aspx?honorificTitleDropDownList=1&nameTextBox=Ojima HTTP/1.1
Host: www.usol-v.com.vn
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; ja; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://www.usol-v.com.vn/TechnicalDocuments/An_Introduction_of_ASP.NET_2.0/Default_ja.htm

Referer là URL của web page đưa ra request, và nó dùng khi phân tích access. Nếu bỏ đi Referer này thì điểm khác biệt chỉ còn phần file name của GET. Cụ thể là phần file name sẽ có dạng là "file name của URL đã được chỉ định bằng thuộc tính action?giá trị thuộc tính name của input item 1=giá trị đã được input vào input item 1&giá trị thuộc tính name của input item 2=giá trị đã được input vào input item 2". (Trong trường hợp <select> thì giá trị thuộc tính value của <option> sẽ được gửi đi. Vì thế,phía sau của honorificTitleDropDownList= của request ban nãy sẽ không phải là "Mr." mà là "1"). Tuy nhiên thì phần phía sau từ ? này sẽ được phân tích dựa vào application server, và nó trở thành parameter đối với Web application.

Trong thuộc tính method của <form> ngoài "get" ra thì cũng có thể chỉ định "post" (Trên thực tế thì phổ biến là chọn "post". Bởi vì trường hợp "get" thì sẽ bị giới hạn độ lớn của parameter có thể gửi đi). Dưới đây chúng tôi đưa ra request trong trường hợp chọn giá trị thuộc tính method là "post".

POST /TechnicalDocuments/An_Introduction_of_ASP.NET_2.0/next-page.aspx HTTP/1.1
Host: www.usol-v.com.vn
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; ja; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost:8090/TechnicalDocuments/An_Introduction_of_ASP.NET_2.0/Default_ja.htm
Content-Type: application/x-www-form-urlencoded
Content-Length: 46
honorificTitleDropDownList=1&nameTextBox=Ojima

Điểm khác nhau chủ yếu khi chọn thuộc tính method là "post" là ở chỗ dòng đầu tiên sẽ chọn là POST thay vì GET, và thay vì add parameter vào sau file name thì sẽ add thêm thông tin đã được input vào sau cùng của request. Ngay cả trong trường hợp POST thì đặc trưng của nó vẫn không hề thay đổi tức là nó vẫn có đặc trưng là nội dung thông tin đơn giản, và tính stateless.

Hoạt động của Web application

Vì đã hiểu về HTML và HTTP nên tôi sẽ giải thích về những hoạt động cụ thể của web application. Dưới đây là những hoạt động của Web application.

  1. Web browser gửi thông tin request của HTTP GET tới application server dựa vào những thông tin đã được input vào URL.
  2. Application server sinh ra HTML và trả về làm response của HTTP.
  3. Web browser phân tích HTML, hiển thị màn hình và gửi thông tin request của HTTP POST dựa vào input của user.
  4. Application thực hiện business logic dựa trên request, tạo HTML mới và trả về làm response của HTTP.
  5. Lặp lại 2-3

Tôi cho rằng các bạn có thể hiểu được sự khác nhau giữa hoạt động của Web application và hoạt động của Visual Basic. ASP.NET 2.0 chính là kỹ thuật giúp giải quyết những sự khác biệt này thông qua nhiều cấu trúc.

Cấu trúc ASP.NET 2.0

ASP.NET 2.0 sẽ cung cấp các cơ cấu để thực hiện phương pháp phát triển tương tự Visual Basic, như là cơ cấu sinh ra event từ postback, HTTP request, và các control được biểu hiện bằng thẻ, hay cơ cấu maintain trạng thái theo ViewState.

Hoạt động của Visual Basic Applciation

Trước tiên, chúng ta cùng suy nghĩ về những hoạt động của Visual Basic Applciation. Theo như hiển thị dưới đây, thì trong Visual Basic Application form là tất cả phần trung tâm.

  1. Tạo form rồi hiển thị.
  2. Khi user thao tác form thì event handler được gọi ra.
  3. Event handler thực hiện logic, set peroperty của control, rồi load lại màn hình.
  4. Lặp lại 2-3.
  5. Tạo và hiển thị form mới nếu cần.
  6. Lặp lại 2-5.

Nếu so sánh với hoạt động của Web application thì chắc các bạn sẽ hiểu được sự khác biệt giữa chúng. Sau đây là 3 điểm khác biệt cụ thể.

Control mà được hiển thị bằng thẻ

Web application và Visual Basic không phải là khác nhau hoàn toàn. Cả HTML sử dụng trên Web application và *.frm biểu thị form của Visual Basic đều có điểm chung là cả 2 đều là cấu trúc cây (mặc dù hoàn toàn không có điểm chung về mặt ngữ pháp). Có form, trong đó có panel (trong HTML là thẻ <div> và thẻ <table>), có text box, button. Tất cả những cái này được gọi là các control biểu thị phần GUI, vì thế nó sẽ có cấu trúc cây, với hình thức như Composite pattern, ở chỗ gọi là design pattern.

Vì thế nên trong ASP.NET có nhiều control với hình thức giống HTMLthẻ trong HTML. Chúng tôi xin được đưa ra source code cụ thể như sau.

<form id="form1" runat="server">
    <p>
        HonoricTitle:
        <asp:DropDownList ID="honorificTitleDropDownList" runat="server">
            <asp:ListItem Text="Mr." Value="1" />
            <asp:ListItem Text="Mrs." Value="2" />
            <asp:ListItem Text="Miss" Value="3" />
        </asp:DropDownList>
    </p>
    <p>
        Name:
        <input type="text" name="nameTextBox" runat="server" />
    </p>
    <p>
        <asp:Button ID="sendDataButton" Text="Send Data to Application Server" runat="server" />
    </p>
</form>

Thẻ mà giá trị của thuộc tính runat được set bằng "server" là control của ASP.NET 2.0. Trong trường hợp tên thẻ bắt đầu bằng "asp:" thì sử dụng control có tên giống với thẻ ở namespace của System.Web.UI.WebControls, các trường hợp khác thì sử dụng control có tên giống với thẻ của HTML ở namespace của System.Web.UI.HtmlControls. Những control này sẽ sinh ra HTML phù hợp khi chạy thông qua runtime của ASP.NET 2.0. Ví dụ trong trường hợp <asp:DropDownList> thì sẽ sinh ra <select>.

Post back

Vì những điểm giống nhau đã kết thúc bằng control biểu thị bằng thẻ nên bây giờ chúng ta sẽ đi sâu vào những điểm khác biệt.

Điểm khác biệt mà chúng ta có thể nghĩ ngay tới chính là nơi gửi request. Do trong Visual Basic thì có thể thực hiện nhiều lần event handler trong những màn hình giống nhau nên không thể tiến hành gửi request tới màn hình tiếp theo như ở Web application thông thường. Mà bắt buộc phải tự gửi lại cho chính mình.

Trong ASP.NET 2.0 gọi việc gửi thông tin request lại cho chính mình được gọi là postback. Về nguồn gốc tên postback nghĩa là việc gửi thông tin request trong Web application như đã trình bày chính là protocol POST của HTTP, và nó sẽ trả lại request đó cho component đã sinh ra HTML.

Cách làm cụ thể để thực hiện post back?

Phương pháp thực hiện post back thì rất đơn giản, chỉ là thao tác đưa URL của chính mình vào thuộc tính action của thẻ <form> để hiển thị form trên HTML. Nếu nhìn vào source code của ASP.NET 2.0 như đã đưa ra thì các bạn sẽ thấy là trong <form> không có thuộc tính action. Vì trong <form> có runat="server" nên nó chính là control của ASP.NET 2.0. Control <form> này sẽ tự động sinh ra thuộc tính action để trỏ vào chính mình khi tạo ra HTML, và thực hiện postback.

Tạo event từ HTTP request

Theo như đã trình bày ở phần "HTTP là gì?" thì request mà gửi thông tin lại cho chính mình bằng postback vô cùng đơn giản.

Để tương ứng với Visual Basic, phải thực hiện chuyển request này thành 1 dạng event nào đó, và cuối cùng các method như sendButton_Click(object source, EventArgs e) phải được gọi ra.

Cách làm cụ thể để tạo event từ HTTP request?

Những thao tác khó sẽ được thực hiện bởi JavaScript (cụ thể là sẽ sinh ra hàm JavaScript có tên __doPostBack) của client site chỉ được sinh ra trong trường hợp logic của runtime ASP.NET 2.0 sử dụng tính năng HTTP request, mà logic của runtime không thể thực hiện được.

Maintain trạng thái theo ViewState

Nếu chỉ sử dụng HTTP một cách thông thường và hiển thị ra thì việc sinh ra event từ HTTP như đã trình bày ở trên là rất khó khăn. Bởi vì HTTP là stateless.

Trong HTTP giữa request trước và request sau này không có quan hệ gì. Cho dù có request được gửi thông tin từ Web browser giống nhau của cùng một computer thì nó cũng không có quan hệ gì cả. Hơn nữa thậm chí là việc tạo event của change series (ví dụ TextChanged) là vô cùng khó khăn.

Chúng ta sẽ cùng đi vào nội dung cụ thể hơn. Trong server site dựa theo HTTP request mà chỉ có thể nhận thông tin của input data, thì cho dù hiểu được nội dung đã input thì vẫn không hiểu được nội dung đã hiển thị trước đó.

Nếu là stateful, có thể hiểu được lần trước đã trả response như thế nào, thế nhưng tiếc là HTTP lại là stateless. Vì thế, cho dù hiều được input là "XX" lần này thì vẫn không hiểu được trước cái đó là "YY" hay là "ZZ". Vì thế nên từ HTTP request thông thường không thể sinh ra event của change series.

Trong HTTP, rất khó để maintain property of control

Chúng ta hãy cùng nhau suy nghĩ sâu hơn nào. Lấy ví dụ về label là control của Visual Basic. Label control là control sẽ hiển thị lên màn hình các character đã được set bởi Text property, và nó được biểu hiện bằng sử dụng thẻ <span> của HTML. Nó không phải là thẻ <input>. Vì thế nên trong HTTP request không bao gồm data của label control.

Hơn nữa, như đã trình bày ở phần trước, HTTP là stateless, nên không biết được ở lần response trước nó trả lại HTML như thế nào? Vì thế, trừ khi có các solution đặc biệt, còn không thì sẽ không thể hiển thị được gì trên Web browser cả trong response trước và sau này.

Nếu như vậy thì chúng ta vẫn chưa thể thực hiện tương đương với Visual Basic. Do vậy bằng cách nào đấy chúng ta buộc phải giữ lại trạng thái trước đó và trong request phải bao gồm cả thông tin liên quan đến trạng thái trước đó.

Cách làm cụ thể để giữ trạng thái theo ViewState?

Thật may, nếu sử dụng thẻ <input type=”hidden”> thì việc add thêm thông tin tới cho request rất đơn giản. Gọi là thẻ <input type=”hidden”> là bởi vì nó là input item không được hiển thị lên màn hình theo đúng như tên gọi của nó, mà sẽ gửi các giá trị đã được chỉ định bằng thuộc tính value.

Trong ASP.NET 2.0, sử dụng thẻ <input type=”hidden”> thì có thể giữ được trạng thái trước đó. Cụ thể là sẽ tạo ra thẻ <input type=”hidden”> mà thuộc tính name được set trong "__VIEWSTATE", để giữ lại trạng thái control chứa trong form vào trong thẻ đó. Trong ASP.NET 2.0 người ta gọi tính năng lưu giữ lại trạng thái bằng phương thức này là ViewState.

Hoạt động của ASP.NET 2.0

Chúng ta sẽ tóm tắt lại những phần trên và trình bày về hoạt động của ASP.NET 2.0. Phần trình bày sẽ dựa trên việc phân chia thành request lần đầu và request từ lần 2 trở đi.

Trường hợp request lần đầu

Nếu ASP.NET 2.0 nhận request HTTP từ Web browser, thì nó sẽ tạo ra form instance. Form instance sẽ tạo ra cây của control instance ở bên trong đó.

Sau đó, cho khởi động Load event, và gọi ra event handler mà chúng ta sẽ tạo. Trong event handler, set property của control trong control cây để kiểm soát việc hiển thị màn hình.

Cuối cùng, Form sẽ sinh ra HTML và trả về Web browser. Xử lí generate HTML được chuyển đến control, control sẽ sinh ra HTML phù hợp với property của chính mình. Hơn nữa, có thể lưu giữ trạng thái của control vào trong ViewState khi cần, và thẻ <input type=”hidden”> sẽ được tạo ra.

Trường hợp request từ lần 2 trở đi

Nội dung cho đến phần nhận request HTTP, tạo cây của form instance và control instance thì giống với request đầu tiên.

Trong postback request bao gồm ViewState tạo trong response trước đó, vì thế sẽ set control property giống như khi trả về response lần trước dựa vào ViewState đó.

Sau đó, so sánh trạng thái giữa HTTP request và trạng thái control hiện tại (được phục hồi nhờ ViewState), thì chúng ta sẽ khởi động event thích hợp. Do form được load tương tự với trường hợp request đầu tiên, nên đầu tiên, load event nếu giá trị được input vào textbox khác với ViewState, và nếu TextChanged event, button được click, thì chúng ta cảm giác như là Clicked event.

Đương nhiên, với các event handler của load event mà cả request đầu tiên, cả postback (Page_Load() method) đều được gọi ra vô điều kiện thì sử dụng IsPostBack property biểu thị là có postback hay không, để thay thế nội dung xử lí. Hãy lấy ví dụ cụ thể. Thông thường Page_Load() method sẽ như sau.

private void Page_Load(object sender, EventArgs e)
{
    //  Sử dụng IsPostBack property, phán đoán xem có postback hay không?
    if (!IsPostBack)
    {
        //  ở đây sẽ mô tả xử lí khởi tạo.
    }
        
    //  Ở đây sẽ mô tả xử lí chung trong tất cả event.
}  

Các request sau giống với request đầu tiên. Control sẽ tạo ra HTML, và ViewState lưu giữ trạng thái sẽ được sinh ra.

Chú ý khi sử dụng ASP.NET 2.0

Theo cấu trúc đã trình bày cho tới đây, thì trong ASP.NET 2.0 chúng ta có thể tạo Web application bằng phương pháp giống với Visual Basic.

Tuy nhiên, chúng ta thử suy nghĩ về cấu trúc ASP.NET đã trình bày cho đến đây, do nó có một chút không giống với Visual Basic nên có một số chú ý. Sau đây chúng tôi xin nêu ra những điểm cần chú ý đó.

Chú ý đến việc không lưu giữ được giá trị field

Cái được lưu giữ trong ViewState thì chỉ là trạng thái của control. Field add vào form không phải là đối tượng được lưu giữ trong ViewState. Vì thế nên source code dưới đây không đáp ứng mong muốn.

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    //  Field không được ViewState bảo lưu
    private string name;

    private void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            name = "Ojima";
        }

        //  name field không được set trong trường hợp postback, 
        //  vì thế hiển thị dòng chữ "Hello, !".
        greetingLabel.Text = string.Format("{0}, {1}!", GetGreetingMessage(), name);
    }

    //  Get câu chào hỏi khớp với thời gian.
    private string GetGreetingMessage()
    {
        DateTime dt = DateTime.Now;

        if (dt.Hour < 10)
        {
            return "Good Morning";
        }

        if (dt.Hour > 18)
        {
            return "Good Night";
        }

        return "Hello";
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Không lưu giá trị field</title>
</head>
<body>
    <form id="form1" runat="server">
        <p><asp:Label ID="greetingLabel" runat="server" /></p>
        <p><asp:Button ID="refreshButton" Text="update màn hình" runat="server" /></p>
    </form>
</body>
</html>

Vì thế nên, để cho nó chạy đúng theo mong muốn thì ta phải viết như dưới đây và lưu property vào trong ViewState.

//  property để access vào giá trị đã được lưu trong ViewState
private string Name
{
    get { return (string)ViewState["Name"]; }
    set { ViewState["Name"] = value; }   
}  

private void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        Name = "Ojima Ryouji";
    }

    //  Name property được lưu trong ViewState
    //  nên không hiện dòng chữ "Hello, !"
    greetingLabel.Text = string.Format("{0}, {1}!", GetGreetingMessage(), Name);
}

Chú ý sử dụng quá ViewState

Như source code đã nêu ra ban nãy, thông tin được set trong ViewState, sẽ được gửi tới Web browser như một phần của HTML, nó được gửi trả lại như một phần của request. Do consume mất mạng nên không sử dụng ViewState đến phần không cần thiết.

Không cần thiết có nghĩa là thông tin đã được thể hiện từ trước như là control property. Thực tế thì trong source code đưa ra ở trên không có gì sai. Nếu chia ra làm 2 control như source code dưới đây thì không cần thay phần tên, bởi vì không sử dụng ViewState như ban đầu thì vẫn kết thúc được.

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    private void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //  Nếu lưu giữ thông tin trong control property 
            //  Thì có thể lưu giữ được thông tin mà không khó khăn gì.
            nameLabel.Text = "Ojima";
        }

        greetingLabel.Text = GetGreetingMessage();
    }

    private string GetGreetingMessage()
    {
        //  Lược bỏ.
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Không sử dụng ViewState trong trường hợp có thể biểu hiện bằng control property.</title>
</head>
<body>
    <form id="form1" runat="server">
        <p><asp:Label ID="greetingLabel" runat="server" />, <asp:Label ID="nameLabel" runat="server" />!</p>
        <p><asp:Button ID="refreshButton" Text="update màn hình" runat="server" /></p>
    </form>
</body>
</html>

Chú ý tới timing của event của change series.

Web browser gửi thông tin request khi bấm button hiển thị bằngthẻ <input type=”submit”>. Chứ không phải là khi update nội dung text box.

Event của change series không quá event được tạo trong server site dựa vào nội dung của request và ViewState. Chúng ta vẫn phải chú ý tới cho dù phát sinh bằng timing mà user thay đổi thực tế và thậm chí cả khi không phát sinh bằng trật tự mà user đã đổi thực tế.

Tôi sẽ đưa ra ví dụ cụ thể. Các bạn hãy nhìn vào source code dưới đây.

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    protected void tên DropDownList_TextChanged(object sender, EventArgs e)
    {
        honorificTitleLabel.Text = tên DropDownList.Text;
    }

    protected void sendtên AndNameButton_Click(object sender, EventArgs e)
    {
        greetingLabel.Text = "Hello, ";
        nameLabel.Text = nameTextBox.Text;
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>chú ý đến timing event của change series</title>
</head>
<body>
    <form id="form1" runat="server">
        <p>
            <!-- 
                Nếu thay đổi giới tính, thì gọi DropDownList_TextChanged() method...
                Cho dù là định làm như thế, nhưng cũng phải sau khi click button thì mới gọi được DropDownList_TextChanged() method  
                
                Nếu thuộc tính AutoPostBack là true thì ngay lập tức DropDownList_TextChanged() method được gọi ra, 
                thế nhưng sẽ chỉ sử dụng trong trường hợp đảm bảo phạm vi mạng rộng.
            -->
            <asp:DropDownList ID="tên DropDownList" runat="server" OnTextChanged="tên DropDownList_TextChanged">
                <asp:ListItem Selected="true" Text="-" Value="" />
                <asp:ListItem Text="male" Value="Mr." />
                <asp:ListItem Text="female" Value="Mrs./Miss" />
            </asp:DropDownList>
            <asp:TextBox ID="nameTextBox" runat="server" />
            <asp:Button ID="sendtên AndNameButton" Text="gửi thông tin về giới tính và tên" runat="server" OnClick="sendtên AndNameButton_Click" />
        </p>
        <p>
            <asp:Label ID="greetingLabel" runat="server" />
            <asp:Label ID="honorificTitleLabel" runat="server" />
            <asp:Label ID="nameLabel" runat="server" />
        </p>
    </form>
</body>
</html>

Mặc dù mong muốn là nếu chọn giới tính, thì nội dung của label tên trang trọng sẽ thay đổi tương ứng cho phù hợp, nhưng đến đây nó lại không hoạt động bình thường. Vì khi click button thì đầu tiên request được gửi đi, Textchange event được tạo ra, và đến lúc đó thì event handler được thực hiện.

Thực ra thì trong ASP.NET 2.0 không có phương pháp khởi động event khi lựa chọn giới tính. Nếu như chọn AutoPostBack property của control đã khởi động event khi thay đổi thành true, và nếu JavaScript được tạo ra và thay đổi thì ngay lập tức sẽ postback.

Thế nhưng, AutoPostBack không phải là phương pháp lúc nào cũng có thể sử dụng được. AutoPostBack chỉ có thể sử dụng trong trường hợp đảm bảo được phạm vi mạng là rộng.

Chúng ta cùng suy nghĩ về trường hợp chọn AutoPostBack là true bằng đường truyền chập chờn. Nếu set AutoPostBack property vào DropDownList của source code ban nãy thì request sẽ được trả về server tại thời điểm chọn giới tính. Thế nhưng do đường truyền chập chờn quá nên không trả về ngay được. Vì thế nên, user lại tiến hành input tên mà màn hình chẳng hề thay đổi. Tuy nhiên khi đang input tên thì đường truyền chập chờn lại được thông nên nó đã trả lại response. Do trả lại response nên Web browser thay màn hình. Trong response đó không có tên mà user đang input dở, vì thế nên tên đang input dở bị mất đi, và user sẽ cảm thấy rất bực mình.

Tóm tắt

ASP.NET 2.0 có khả năng tạo Web application bằng phương pháp phát triển giống với Visual Basic. Có phương pháp làm cho cấu trúc Web application trở lên vô cùng đơn giản, nếu như không hiểu đúng về cấu trúc đó mà lại sử dụng nó thì có khả năng sẽ không hoạt động như mong muốn, không thể có được performance theo mong muốn sử dụng.

Con đường ngắn nhất để hiểu được cấu trúc của ASP.NET 2.0 là hiểu được HTML và HTTP, sau đó thì hiểu xem là ASP.NET 2.0 chạy bằng cấu trúc như thế nào. Để làm được điều ấy, các bạn hãy tận dụng tối đa cuốn sách này.

Go to .NET Center
Copyright (C) 2007 USOL Vietnam. All right reserved.