Cho đến thời điểm này chúng ta chỉ mới tạo được một website tĩnh, với dữ liệu (nội dung, bố cục, menu, v.v.) được thêm vào trang một cách cố định. Tuy nhiên, chúng ta có thể tạo ra một website hấp dẫn hơn bằng cách kết hợp các dữ liệu động. Các dữ liệu động này có thể đến từ server (các files, databases, v.v.) hay đến từ người dùng nhập từ web browser và gửi trở lại server – phổ biến nhất là nhập dữ liệu từ một webform và submit nó đến server.

Để ngăn chặn những dữ liệu không hợp lệ, điều đầu tiên là phải hợp lệ hoá những dữ liệu trước khi cho phép hệ thống website làm việc với chúng. ASP.NET 4.5 cung cấp cho chúng ta một bộ các công cụ để làm nhiệm vụ này một cách đơn giản nhất. Chương này sẽ tìm hiểu về chúng và một số kĩ thuật có ích khác.

Thu thập dữ liệu người dùng

Dữ liệu người dùng có thể được gửi đến server bằng nhiều cách, phổ biến nhất là dùng phương thức GETPOST.

Với GET, chúng ta dùng chuỗi truy vấn (xem lại cuối chương VII – phần Lập trình chuyển trang) bằng thuộc tính QueryString của đối tượng Request. Ví dụ chúng ta có URL kèm theo chuỗi truy vấn như sau:

http://www.PlanetWrox.com/Reviews/ViewDetails.aspx?ReviewId=34&CategoryId=3

Có thể truy cập đến các thành phần của chuỗi truy vấn này, ví dụ ReviewId hay CategoryId,  bằng phương thức GET của collection QueryString (lưu ý đây là collection chứ không phải thuộc tính như trên) như sau:


' Gán giá trị của ReviewId (34) đến biến reviewId

Dim reviewId As Integer = Convert.ToInt32(Request.QueryString.Get("ReviewId"))

' Gán giá trị CategoryId (3) đến biến categoryId

Dim categoryId As Integer = Convert.ToInt32(Request.QueryString.Get("CategoryId"))

Với POST, không cần đến chuỗi truy vấn, mà lấy dữ liệu trực tiếp từ form thông qua các controls. Ví dụ, chúng ta có một form gồm một textbox gọi là Age (thuộc tính ID) dùng để nhập tuổi người dùng và một button dùng để submit tuổi người dùng đến server, trong sự kiện Click của button có thể viết dòng code như sau:


' gán tuổi người dùng (từ textbox Age) đến biến age

Dim age As Integer = Convert.ToInt32(Age.Text)

Sẽ không vấn đề gì nếu người dùng nhập dữ liệu hợp lệ, như 30 chẳng hạn, nhưng nếu người dùng, thay vì nhập một số sẽ nhập một chuỗi, như I am 30 chẳng hạn, thì phương thức ToInt32 sẽ báo lỗi bằng cách phát sinh một ngoại lệ.

Như vậy, chúng ta cần phải có một cách nào đó để kiểm tra (hay hợp lệ hoá) các dữ liệu được nhập bởi người dùng. Chúng ta có thể viết vài đoạn code (snippets), bằng các ngôn ngữ hướng client như JavaScript, để kiểm soát người dùng ngay tại trình duyệt web, nhưng một vài người dùng am hiểu kĩ thuật, hacker chẳng hạn, có thể dễ dàng vô hiệu hoá các đoạn mã JavaScript viết trực tiếp tại trình duyệt, dễ dàng vượt qua các rào cản và gửi dữ liệu nguy hiểm đến server.

ASP.NET cung cấp một loạt các validation controls để giúp chúng ta kiểm soát dữ liệu người dùng ngay tại server, cụ thể là 6 validation controls với 5 trong số chúng thực hiện công việc xử lí dữ liệu người dùng và control thứ 6 – ValidationSumamary – dùng để cung cấp một cảnh báo đến người dùng nếu lỗi xảy ra.

Điểm tuyệt vời nhất của các validation controls là chúng có thể kiểm tra dữ liệu người dùng tại cả client lẫn server. Khi thêm một validation control vào trang, control sẽ sinh ra một đoạn mã JavaScript để kiểm tra dữ liệu người dùng tại trình duyệt web, đồng thời kiểm tra dữ liệu người dùng tại server một cách tự động. Với các validation control, hệ thống website của chúng ta sẽ được bảo vệ bởi hai tầng (client – server).

Làm quen các validation controls

Để hiểu cách dùng các validation controls chúng ta sẽ thực hiện bài thực hành sau.

Thực hành dùng RequiredFieldValidator control

Trong phần thực hành này chúng ta sẽ tạo ra một user control gọi là ContactForm.ascx. Chúng ta có thể đặt nó trong một trang web để người dùng nhập một vài thông tin đơn giản, trong phần thực hành sau chúng ta sẽ mở rộng user control để cho phép người dùng gửi thông tin đến tài khoản e-mail của bạn.

  • Thêm một user control tên ContactForm.ascx đến thư mục Controls (có thể xem lại cách tạo Banner.ascx ở chương VIII).
  • Chuyển ContactForm.ascx sang chế độ Design. Vào Table > Insert Table để tạo một bảng 8 hàng 3 cột.
  • Bôi đen 3 ô hàng đầu tiên, nhấp chuột phải chọn Modify > Merge Cells để nhập 3 ô thành một. Trong ô mới này, chúng ta có thể gõ vài thông tin đến người dùng.
  • Tại hàng thứ hai, ô đầu tiên gõ từ Tên, ô thứ hai chứa một textbox được kéo từ Toolbox với IDName, ô thứ ba chứa RequireFieldValidator được kéo từ mục Validation của Toolbox. Tại hàng cuối cùng, ô thứ hai chúng ta thêm một button với thuộc tính TextSendIDSendButton. Giao diện lúc này như sau:

  • Chọn RequireFieldValidator và mở hộp thoại Properties để thiết lập một số thuộc tính sau:

  • Lưu tất cả và đóng ContactForm.ascx .
  • Thêm đoạn css sau vào file Monochrome.cssDarkGrey.css và lưu lại:
    .ErrorMessage { color: Red; }
  • Mở trang Contact.aspx trong thư mục About ở chế độ Source, kéo ContactForm.ascx từ thư mục Control trong cửa sổ Solution Explorer và thả vào vùng cpMainContent:

VS sẽ dùng lại ngocminhtran (TagPrefix) đã được khai báo khi chúng ta tạo Banner.ascx.

  • Mở Web.config, trong <configuration> thêm phần tử <appSettings> kèm phần tử con của nó là <add>, mục đích là để vô hiệu chức năng đòi hỏi jQuery (sẽ được thảo luận chương sau):

  • Lưu tất cả. Chọn trang Contact.aspxCtrl + F5. Để textbox rỗng và nhấn nút Send sẽ xuất hiện dấu * màu đỏ bên phải:

  • Nhập thông tin vào textbox và nhấn Send, trang gửi thành công đến server và dấu * đỏ biến mất:

 

Dùng các kiểu dữ liệu HTML5

HTML5 giới thiệu một số kiểu mới cho thuộc tính type của phần tử input. Các kiểu mới cho phép chúng ta quyết định cách trình duyệt web hiểu trường dữ liệu như thế nào. ASP.NET 4.5 cung cấp các kiểu mới của HTML5 thông qua thuộc tính TextMode của Textbox. Những kiểu cũ đã được hỗ trợ trong ASP.NET 1.0 như SingleLine, MultiLine hay Password vẫn giữ nguyên, bên cạnh đó là một vài kiểu mới sau:

Thuộc tính Mô tả
Color Cho phép người dùng chọn màu sắc, thường là từ color picker.
Date/DateTime/

DateTimeLocal/

Month/Week/Time

Cho phép người dùng nhập date hay time theo nhiều cách khác nhau.
Email Cho phép nhập một địa chỉ email.
Url Cho phép nhập địa chỉ website.
Number Cho phép nhập một số.
Range Cho phép nhập một số trong một phạm vi nào đó.
Search Cho phép người dùng nhập một mục tìm kiếm.

Các kiểu này là giá trị của thuộc tính TextMode sẽ được chuyển từ server đến trình duyệt với cùng tên nhưng theo dạng chữ thường, ví dụ Email thành emai như sau:

Server

<asp:TextBox runat="server" ID="Email" TextMode="Email" />

Browser

<input name="Email" type="email" id="Email" />

Tuy nhiên, chúng ta cần chú ý khi dùng những kiểu HTML5:

  • HTML5 sẽ chỉ hỗ trợ các trình duyệt phiên bản mới
  • Sự hỗ trợ các kiểu HTML5 cho các trình duyệt khác nhau là khác nhau.
  • Những kiểu mới sẽ không an toàn cho việc hợp lệ hoá dữ liệu.

Các validation controls chuẩn

Các validation controls chứa trong mục Validation của Toolbox. Các controls này đều được xây dựng sẵn các tập luật phục vụ việc hợp lệ dữ liệu người dùng, trừ control cuối cùng, CustomValidator, cho phép chúng ta bổ sung thêm các luật theo mục đích riêng.

Các validation controls chia sẻ chung các thuộc tính sau

Thuộc tính Mô tả
Display Cho phép hiển thị thông điệp lỗi, rất có ích khi dùng ValidationSummary.
CssClass ứng dụng lớp css đến thông điệp lỗi.
ErrorMessage Thông điệp lỗi dùng trong ValidationSummary. Khi thuộc tính Text rỗng, giá trị của thuộc tính này sẽ thay thế.
Text Lưu trữ text mà control sẽ hiển thị trên trang.
ControlToValidate Chứa ID của control cần hợp lệ.
EnableClientScript Quyết định liệu control có cung cấp cơ chế hợp lệ tại trình duyệt hay không (một đoạn JavaSript chẳng hạn). Mặc định là True.
SetFocusOnError Xác định liệu script (client) cho một focus đến control đầu tiên phát sinh lỗi. Mặc định là False.
ValidationGroup Có thể nhóm các validation controls lại cùng nhau, quá trình hợp lệ sẽ diễn ra tại cùng một thời điểm cho tất cả các control trong nhóm.
IsValid Không thể thiết lập giá trị tại thời điểm thiết kế (design time), nhưng tại thời điểm thực thi (run time), nó cung cấp thông tin liệu quá trình hợp lệ có thành công không.

Chúng ta đã tìm hiểu cách dùng RequiredFieldValidator ở bài thực hành trên. Phần kế tiếp chúng ta sẽ tìm hiểu các controls còn lại.

RangeValidator

Cho phép kiểm tra một giá trị có thuộc phạm vi cho phép hay không. Một số thuộc tính cơ bản (bên cạnh các thuộc tính chung đã nêu trên):

Thuộc tính Mô tả
MinimumValue Cho phép giá trị hợp lệ thấp nhất.
MaximumValue Cho phép giá trị hợp lệ cao nhất.
Type Xác định kiểu dữ liệu của giá trị cần kiểm tra (Date, String, Integer, v.v.)

Ví dụ đảm bảo giá trị nhập vào textbox Rate là một số nguyên từ 1 đến 10:

<asp:RangeValidator ID="RangeValidator1" runat="server" ControlToValidate="Rate" ErrorMessage="Nhập một số giữa 1 và 10" MaximumValue="10" MinimumValue="1" Type="Integer" />

RegularExpressionValidator

Cho phép kiểm tra tính hợp lệ các dữ liệu phức tạp như địa chỉ email, ZIP code, v.v. Các luật cho các dữ liệu này được thiết lập dựa trên biểu thức thường quy (regular expression). Ví dụ kiểm tra tính hợp lệ một địa chỉ email:

<asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" ControlToValidate="Email"  ErrorMessage="Nhập một email hợp lệ" ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" />

CompareValidator

Dùng để so sánh giá trị của một control với giá trị một control khác. Chúng ta có thể thấy điều này trong form đăng nhập, phần xác nhận mật khẩu. Một số thuộc tính cơ bản (bên cạnh các thuộc tính chung ở trên):

Thuộc tính Mô tả
ControlToCompare Chứa ID của control muốn so sánh.
Operator Xác định toán tử so sánh (Equal, NotEqual, v.v.)
Type Xác định kiểu dữ liệu (String, Integer, v.v.)
ValueToCompare So sánh với giá trị hằng được định nghĩa trước.

Ví dụ đảm bảo hai textbox có cùng password:

<asp:CompareValidator ID="CompareValidator1" runat="server" ControlToCompare="ConfirmPassword" ControlToValidate="Password" ErrorMessage="Your passwords don't match" />

Thực hành dùng validation controls

Trong bài thực hành này chúng ta sẽ mở rộng ContactForm bằng cách thêm các trường để người dùng cung cấp thêm thông tin về địa chỉ email, số điện thoại cá nhân hay cơ quan và một vài ghi chú. Địa chỉ email để đảm bảo chính xác phải được nhập hai lần, số điện thoại phải được nhập ít nhất một trong hai số.

  • Mở file ContacForm.ascx trong thư mục Controls ở chế độ Design.
  • Kéo 5 textbox từ Toolbox và thả vào 5 ô ở cột thứ hai, giữa textbox nhập tên và nút Send. Thiết lập ID các textbox từ trên xuống lần lượt là EmailAddress, ConfirmEmailAddress, PhoneHome, PhoneBusiness, Comments.Thêm vài đoạn text ở các ô cột đầu tiên mô tả từng text box vừa thêm vào. Thiết lập thuộc tính TextMode của textbox CommentsMultiLine và mở rộng textbox này thêm để tiện cho người dùng nhập thông tin. Thiết lập thuộc tính TextMode của EmailAddressConfirmEmailAddressEmail. Giao diện trông như sau:

  • Trên hàng Địa chỉ Emai, tại ô cuối cùng, kéo và thả vào một RequiredFieldValidator và một RegularExpressionValidator; trên hàng Xác nhận địa chỉ Email, tại ô cuối cùng, kéo và thả vào một RequiredFieldValidator và một CompareValidator. Cuối cùng, tại ô cuối cùng của hàng Chú thích, kéo và thả một RequiredFieldValidator:

  • Chọn tất cả validation controls vừa thêm vào (RequiredFieldValidator, RegularExpressionValidator , CompareValidator) một lần (chọn một control, nhấn phím Ctrl và chọn các controls khác) và vào hộp thoại Properties thiết lập thuộc tính Text là dấu *, thuộc tính DisplayDynamic, thuộc tính, và CssClassErrorMessage.
  • Các thuộc tính còn lại của các validation controls được thiết lập như sau:
Control Thuộc tính Giá trị
RequiredFieldValidator (cho Địa chỉ Email) ErrorMessage Nhập địa chỉ Email
ControlToValidate EmailAddress
RegularExpressionValidator ErrorMessage Nhập địa chỉ Email hợp lệ
ControlToValidate EmailAddress
ValidationExpression Nhấp vào nút bên phải và chọn Internet e-mail address
RequiredFieldValidator (cho Xác nhận địa chỉ Email) ErrorMessage Xác nhận địa chỉ Email
ControlToValidate ConfirmEmailAddress
CompareValidator ErrorMessage Email không khớp nhau
ControlToCompare EmailAddress
ControlToValidate ConfirmEmailAddress
RequiredFieldValidator (cho Chú thích) ErrorMessage Nhập một chú thích
ControlToValidate Comments
  • Lưu và đóng ContactForm.ascx. Chọn trang Contact.aspx từ thư mục AboutCtrl + F5. Để trống các textbox và bấm Send:

  • Nhập Email sai định dạng:

  • Nhập email không khớp nhau:

  • Nhập phù hợp:

Bài thực hành trên dùng các validation controls để cảnh báo người dùng khi nhập thiếu thông tin hay nhập sai định dạng thông tin nhưng vẫn chưa có những thông báo chỉ dẫn cụ thể, rõ ràng. Chúng ta sẽ làm điều này nhờ CustomValidatorValidationSummary.

CustomValidator cho phép bạn viết các chức năng kiểm tra tính hợp lệ dữ liệu người dùng ở client (JavaScript) và server (C# hay VB). ValidationSummary cung cấp cho người dùng một danh sách các lỗi nhận được từ thuộc tính ErrorMessage của các controls. Các lỗi này có thể được hiển thị theo 3 cách: nhúng trực tiếp danh sách vào trang, dùng phương thức alert trong JavaScript hay kết hợp cả hai cách. Các thuộc tính quan trọng của ValidationSummaryShowMessageBox, ShowSummary, DisplayMode. Chúng ta sẽ hiểu hơn về hai controls này qua bài thực hành sau đây.

Thực hành dùng CustomValidator và ValidationSummary

Chúng ta dùng CustomValidator trong trang để đảm bảo ít nhất một trong hai số điện thoại phải được nhập. Dùng ValidationSummary để cung cấp phản hồi các lỗi cho người dùng.

  • Mở ContactForm.ascx ở chế độ Design, chọn hàng cuối cùng của bảng (chứa nút Send) và kích chuột phải chọn Insert > Row Below để thêm một hàng mới. Khi xuất hiện hàng mới, chọn cả 3 ô của hàng mới này và nhấp chuột phải chọn Modify > Merge Cells để trộn 3 ô thành 1.
  • Kéo một ValidationSummary từ mục Validation của Toolox và thả vào hàng cuối với một ô duy nhất vừa tạo. Thiết lập thuộc tính CssClass đến ErrorMessage.
  • Kéo một CustomValidator và thả vào ô trống (ô cuối cùng) sau textbox Số điện thoại cá nhân. Thiết lập các thuộc tính đến các giá trị như sau:
Thuộc tính Giá trị
CssClass ErrorMessage
Display Dynamic
ErrorMessage Nhập số điện thoại cá nhân hay số cơ quan
Text *
ClientValidationFunction     validatePhoneNumbers (là một phương thức JavaScript)
  • Nhấp đôi chuột vào CustomValidator để đến trình xử lí sự kiện ServerValidate và thêm một vài đoạn mã sau:

  • Chuyển ContactForm.ascx đến chế độ Source và thêm đoạn mã JavaScript của phương thức validatePhoneNumbers (trong cặp thẻ <script>) phía trên thẻ <table> như sau:

  • Lưu tất cả và đóng ContactForm.ascx . Chọn trang Contact.aspxCtrl + F5, bấm nút Send:

  • Mở lại ContactForm.ascx ở chế độ Design, chọn ValidationSummary và thiết lập thuộc tính ShowMessageBox đến TrueShowSummary đến False. Thiết lập HeaderText đến Xin hãy nhập đầy đủ thông tin bên dưới:
  • Lưu và mở lại trang Contact.aspx, Ctrl + F5 và bấm nút Send sẽ xuất hiện hộp thoại cảnh báo sau:

Yêu cầu hợp lệ (request validation)

Mặc định, các controls trong trang ASP.NET sẽ không cho phép nhập nội dung là các đoạn mã HTML hay các script, ví dụ nhập đoạn mã <h1> Hello </h1> vào textbox Chú thích thì trang ASP.NET sẽ phát sinh một ngoại lệ như sau:

Mục đích là để ngăn chặn người dùng nhập những đoạn mã độc hại gây nguy hiểm cho hệ thống website. Tuy nhiên, trong một vài trường hợp chúng ta cho phép người dùng nhập các đoạn mã HTML hay các script. Muốn làm điều này, ví dụ với trang Contact.aspx, chúng ta tìm đến <%@ page> ở đầu trang và thiết lập thuộc tính ValidateRequest đến False và lúc này nếu nhập lại đoạn mã HTML sẽ không còn lỗi.

Tuy nhiên, nếu dùng cách này thì mọi controls trong trang đều cho phép người dùng nhập đoạn mã HTML hay Script và chúng ta chỉ muốn một vài controls cho phép nhập, một vài controls khác thì không. ASP.NET 4.5 cung cấp thuộc tính ValidateRequestMode cho các controls. Thuộc tính này có 3 giá trị là Enabled không cho phép nhập mã HTML hay Script, Disable cho phép nhập HTML hay Script và Inherit kế thừa giá trị của control cha như PlaceHolder (trong trường hợp chúng ta nhóm các control trong một PlaceHolder).

Đọc nội dung từ tập tin văn bản (text files)

.NET Framework cung cấp nhiều lớp và phương thức cho phép làm việc dễ dàng với các tập tin. Với các tập tin văn bản, lớp File chứa trong namespace System.IO được dùng phổ biến. Lớp File chứa các phương thức sau:

Phương thức Chức năng
AppendAllText Thêm một chuỗi kí tự đến một file văn bản. Nếu file văn bản này chưa tồn tại thì phải tạo ra nó đầu tiên.
Copy Sao chép một tập tin từ một vị trí đến vị trí khác.
Delete Xoá một tập tin từ nơi ổ đĩa lưu trữ.
Exists Kiểm tra một file có tồn tại hay không.
Move Di chuyển file đến vị trí khác.
ReadAllText Đọc nội dung của một tập tin văn bản.
WriteAllText Ghi nội dung đến một file mới, ghi đè lên nội dung đã có nếu file đã tồn tại.

Chúng ta sẽ hiểu hơn lớp File và các phương thức của nó thông qua phần thực hành sau.

Thực hành với tập tin văn bản

  • Tạo một thư mục mới tên App_Data trong Site. Thêm một tập tin văn bản tên txt bằng cách nhấp chuột phải vào App_Data chọn Add > Add New Item > Text File, gõ tên file là Text.txt và nhấn Add.
  • Trong trong Text.txt gõ nội dung sau, lưu ý rằng có các chuỗi được chứa trong cặp ## gọi là các PlaceHolder dùng để chứa nội dung của các textbox :

  • Lưu và đóng Text.txt. Mở file ContactForm.ascx.vb chèn thêm namespace System.IO bằng lệnh Imports hàng đầu tiên:

  • Mở file ContactForm.ascx ở chế độ Source, thêm các thuộc tính runatid vào <table>. Bằng cách này, table đã trở thành một server control và sẽ ẩn khi xem ở client (trình duyệt web)

  • Tìm đến vị trí dưới </table>, thêm một Label với các thuộc tính như sau:

  • Mở ContactForm.ascx ở chế độ Design, nhấp đôi chuột vào nút Send để đến sự kiện Click và viết vài dòng mã sau:

  1. Lưu. Chọn trang Contact.aspxCtrl + F5, gõ một vài thông tin vào Form và bấm Send:

Kết quả sau khi nhấn Send: