驗證 ASP.NET Web Pages (Razor) 網站中的使用者輸入

作者:Tom FitzMacken

本文討論如何驗證您從使用者取得的資訊,也就是確定使用者在 ASP.NET Web Pages (Razor) 網站中以 HTML 表單輸入有效資訊。

您將學到什麼:

  • 如何檢查使用者的輸入是否符合您定義的驗證準則。
  • 如何判斷是否已通過所有驗證測試。
  • 如何 (顯示驗證錯誤,以及如何將其格式化) 。
  • 如何驗證不直接來自使用者的資料。

以下是文章仲介紹的 ASP.NET 程式設計概念:

  • 協助 Validation 程式。
  • Html.ValidationSummaryHtml.ValidationMessage 方法。

教學課程中使用的軟體版本

  • ASP.NET Web Pages (Razor) 3

本教學課程也適用于 ASP.NET Web Pages 2。

本文包含下列各節:

使用者輸入驗證概觀

如果您要求使用者在頁面中輸入資訊,例如在表單中輸入資訊,請務必確定他們輸入的值有效。 例如,您不想處理遺漏重要資訊的表單。

當使用者在 HTML 表單中輸入值時,他們輸入的值是字串。 在許多情況下,您需要的值是一些其他資料類型,例如整數或日期。 因此,您也必須確定使用者輸入的值可以正確地轉換成適當的資料類型。

您可能也有值的特定限制。 例如,即使使用者正確輸入整數,您可能需要確定該值落在特定範圍內。

此螢幕擷取畫面顯示使用 CSS 樣式類別的驗證錯誤。

注意

重要 驗證使用者輸入對於安全性也很重要。 當您限制使用者可以在表單中輸入的值時,您可以減少有人輸入可能會危害網站安全性的值的機會。

驗證使用者輸入

在 ASP.NET Web Pages 2 中,您可以使用 Validator 協助程式來測試使用者輸入。 基本方法是執行下列動作:

  1. 判斷您要驗證) 欄位 (輸入元素。

    您通常會在表單中的元素中 <input> 驗證值。 不過,驗證所有輸入是很好的作法,即使是來自清單等受限元素的 <select> 輸入也一樣。 這有助於確保使用者不會略過頁面上的控制項並提交表單。

  2. 在頁面代碼中,使用協助程式的方法 Validation ,為每個輸入專案新增個別的驗證檢查。

    若要檢查必要欄位,請使用 Validation.RequireField(field, [error message]) 個別欄位 () ,或 Validation.RequireFields(field1, field2, ...)) 針對欄位清單使用 () 。 如需其他類型的驗證,請使用 Validation.Add(field, ValidationType) 。 針對 ValidationType ,您可以使用下列選項:

    Validator.DateTime ([error message])
    Validator.Decimal([error message])
    Validator.EqualsTo(otherField [, error message])
    Validator.Float([error message])
    Validator.Integer([error message])
    Validator.Range(min, max [, error message])
    Validator.RegEx(pattern [, error message])
    Validator.Required([error message])
    Validator.StringLength(length)
    Validator.Url([error message])

  3. 提交頁面時,請檢查驗證是否已通過,方法是檢查 Validation.IsValid

    if(IsPost && Validation.IsValid()){
        // Process form submit
    }
    

    如果有任何驗證錯誤,您可以略過一般頁面處理。 例如,如果頁面的目的是要更新資料庫,在修正所有驗證錯誤之前,您不會這麼做。

  4. 如果有驗證錯誤,請使用 Html.ValidationSummaryHtml.ValidationMessage 或 ,在頁面標記中顯示錯誤訊息。

下列範例顯示說明這些步驟的頁面。

@{
    var message="";
    // Specify validation requirements for different fields.
    Validation.RequireField("coursename", "Class name is required");
    Validation.RequireField("credits", "Credits is required");
    Validation.Add("coursename", Validator.StringLength(5));
    Validation.Add("credits", Validator.Integer("Credits must be an integer"));
    Validation.Add("credits", Validator.Range(1, 5, "Credits must be between 1 and 5"));
    Validation.Add("startDate", Validator.DateTime("Start date must be a date"));

    if (IsPost)  {
        // Before processing anything, make sure that all user input is valid.
        if (Validation.IsValid()) {
            var coursename = Request["coursename"];
            var credits = Request["credits"].AsInt();
            var startDate = Request["startDate"].AsDateTime();
            message += @"For Class, you entered " + coursename;
            message += @"<br/>For Credits, you entered " + credits.ToString();
            message += @"<br/>For Start Date, you entered " + startDate.ToString("dd-MMM-yyyy");

            // Further processing here
        }
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Validation Example</title>
  <style>
      body {margin: 1in; font-family: 'Segoe UI'; font-size: 11pt; }
   </style>
</head>
<body>
  <h1>Validation Example</h1>
  <p>This example page asks the user to enter information about some classes at school.</p>
  <form method="post">
    @Html.ValidationSummary()
    <div>
      <label for="coursename">Course name: </label>
      <input type="text"
         name="coursename"
         value="@Request["coursename"]"
      />
      @Html.ValidationMessage("coursename")
    </div>

    <div>
      <label for="credits">Credits: </label>
      <input type="text"
         name="credits"
         value="@Request["credits"]"
      />
      @Html.ValidationMessage("credits")
    </div>

    <div>
      <label for="startDate">Start date: </label>
      <input type="text"
         name="startDate"
         value="@Request["startDate"]"
      />
      @Html.ValidationMessage("startDate")
    </div>

   <div>
      <input type="submit" value="Submit" class="submit" />
    </div>

    <div>
      @if(IsPost){
        <p>@Html.Raw(message)</p>
      }
    </div>
  </form>
</body>
</html>

若要查看驗證的運作方式,請執行此頁面並刻意進行錯誤。 例如,如果您忘記輸入課程名稱,以及輸入不正確日期,頁面看起來會像這樣:

轉譯頁面中的驗證錯誤

加入用戶端驗證

根據預設,使用者輸入會在使用者提交頁面之後進行驗證,也就是在伺服器程式碼中執行驗證。 這種方法的缺點是使用者不知道在提交頁面之前發生錯誤。 如果表單很長或複雜,則只有在提交頁面之後報告錯誤才對使用者不方便。

您可以新增支援,以在用戶端腳本中執行驗證。 在此情況下,驗證會在使用者在瀏覽器中運作時執行。 例如,假設您指定值應該是整數。 如果使用者輸入非整數值,當使用者離開輸入欄位時,就會立即報告錯誤。 使用者會收到立即的意見反應,這很方便他們。 用戶端型驗證也可以減少使用者必須提交表單來更正多個錯誤的次數。

注意

即使您使用用戶端驗證,驗證一律也會在伺服器程式碼中執行。 在伺服器程式碼中執行驗證是安全性措施,以防使用者略過用戶端型驗證。

  1. 在頁面中註冊下列 JavaScript 程式庫:

    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.2.js">
    </script>
    <script
    src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.8.1/jquery.validate.js">
    </script>
    <script src="~/Scripts/jquery.validate.unobtrusive.js">
    </script>
    

    兩個程式庫可從內容傳遞網路載入 (CDN) ,因此您不一定必須在電腦或伺服器上擁有它們。 不過,您必須有 本機複本,jquery.validate.unobtrusive.js。 如果您尚未使用 WebMatrix 範本 (,例如包含程式庫的 入門網站 ) ,請建立以 入門網站為基礎的網頁網站。 然後將 .js 檔案複製到您目前的網站。

  2. 在標記中,針對您要驗證的每個專案,新增對 的 Validation.For(field) 呼叫。 這個方法會發出用戶端驗證所使用的屬性。 (方法會發出類似 data-val-... 的屬性,而不是發出實際的 JavaScript 程式碼。這些屬性支援使用 jQuery 執行工作的非干擾用戶端驗證。)

下列頁面示範如何將用戶端驗證功能新增至稍早所示的範例。

@{
    // Note that client validation as implemented here will work only with
    // ASP.NET Web Pages 2.

    var message="";
    // Specify validation requirements for different fields.
    Validation.RequireField("coursename", "Class name is required");
    Validation.RequireField("credits", "Credits is required");
    Validation.Add("coursename", Validator.StringLength(5));
    Validation.Add("credits", Validator.Integer("Credits must be an integer"));
    Validation.Add("credits", Validator.Range(1, 5, "Credits must be between 1 and 5"));
    Validation.Add("startDate", Validator.DateTime("Start date must be a date"));

    if (IsPost)  {
        // Before processing anything, make sure that all user input is valid.
        if (Validation.IsValid()) {
            var coursename = Request["coursename"];
            var credits = Request["credits"].AsInt();
            var startDate = Request["startDate"].AsDateTime();
            message += @"For Class, you entered " + coursename;
            message += @"<br/>For Credits, you entered " + credits.ToString();
            message += @"<br/>For Start Date, you entered " + startDate.ToString("dd-MMM-yyyy");

            // Further processing here
        }
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Validation Example with Client Validation</title>
  <style>
      body {margin: 1in; font-family: 'Segoe UI'; font-size: 11pt; }
   </style>
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.2.js"></script>
    <script
        src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.8.1/jquery.validate.js">
    </script>
    <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
</head>
<body>
  <h1>Validation Example with Client Validation</h1>
  <p>This example page asks the user to enter information about some classes at school.</p>
  <form method="post">
    @Html.ValidationSummary()
    <div>
      <label for="coursename">Course name: </label>
      <input type="text"
         name="coursename"
         value="@Request["coursename"]"
         @Validation.For("coursename")
      />
      @Html.ValidationMessage("coursename")
    </div>

    <div>
      <label for="credits">Credits: </label>
      <input type="text"
         name="credits"
         value="@Request["credits"]"
         @Validation.For("credits")
      />
      @Html.ValidationMessage("credits")
    </div>

    <div>
      <label for="startDate">Start date: </label>
      <input type="text"
         name="startDate"
         value="@Request["startDate"]"
         @Validation.For("startDate")
      />
      @Html.ValidationMessage("startDate")
    </div>

   <div>
      <input type="submit" value="Submit" class="submit" />
    </div>

    <div>
      @if(IsPost){
        <p>@Html.Raw(message)</p>
      }
    </div>
  </form>
</body>
</html>

並非所有驗證檢查都會在用戶端上執行。 特別是,資料類型驗證 (整數、日期等) 不會在用戶端上執行。 下列檢查適用于用戶端和伺服器:

  • Required
  • Range(minValue, maxValue)
  • StringLength(maxLength[, minLength])
  • Regex(pattern)
  • EqualsTo(otherField)

在此範例中,有效日期的測試無法在用戶端程式代碼中運作。 不過,測試將會在伺服器程式碼中執行。

格式化驗證錯誤

您可以定義具有下列保留名稱的 CSS 類別,來控制驗證錯誤的顯示方式:

  • field-validation-error. 定義方法顯示錯誤時的輸出 Html.ValidationMessage
  • field-validation-valid. 當沒有錯誤時, Html.ValidationMessage 定義 方法的輸出。
  • input-validation-error. 定義在發生錯誤時如何 <input> 呈現專案。 (例如,如果輸入元素的值無效,您可以使用這個類別將輸入 > 元素的背景色彩設定為不同的色彩 < 。) 此 CSS 類別只有在用戶端驗證 (ASP.NET Web Pages 2) 期間才會使用。
  • input-validation-valid. 定義沒有錯誤時元素 <input> 的外觀。
  • validation-summary-errors. 定義其顯示錯誤清單的方法輸出 Html.ValidationSummary
  • validation-summary-valid. 當沒有錯誤時, Html.ValidationSummary 定義 方法的輸出。

下列 <style> 區塊顯示錯誤狀況的規則。

<style>
.validation-summary-errors {
  border:2px solid red;
  color:red;
  font-weight:bold;
  margin:6px;
  width:30%;
}

.field-validation-error{
  color:red;
   font-weight:bold;
   background-color:yellow;
}

.input-validation-error{
  color:red;
  font-weight:bold;
  background-color:pink;
}
</style>

如果您在文章稍早的範例頁面中包含此樣式區塊,則錯誤顯示看起來會像下圖所示:

使用 CSS 樣式類別的驗證錯誤

注意

如果您未在 ASP.NET Web Pages 2 中使用用戶端驗證,則元素的 CSS 類別 <input> 會 (input-validation-errorinput-validation-valid 沒有任何作用。

靜態和動態錯誤顯示

CSS 規則會以配對方式出現,例如 validation-summary-errorsvalidation-summary-valid 。 這些配對可讓您定義這兩個條件的規則:錯誤條件和「正常」 (非錯誤) 條件。 請務必瞭解錯誤顯示標記一律會轉譯,即使沒有任何錯誤也一樣。 例如,如果頁面在 Html.ValidationSummary 標記中有方法,即使第一次要求頁面,頁面來源也會包含下列標記:

<div class="validation-summary-valid" data-valmsg-summary="true"><ul></ul></div>

換句話說, Html.ValidationSummary 方法一律會 <div> 轉譯元素和清單,即使錯誤清單是空的。 同樣地, Html.ValidationMessage 方法一律會將 <span> 專案轉譯為個別欄位錯誤的預留位置,即使沒有錯誤也一樣。

在某些情況下,顯示錯誤訊息可能會導致頁面重排,而且可能會導致頁面上的元素四處移動。 結尾 -valid 的 CSS 規則可讓您定義可協助防止此問題的配置。 例如,您可以定義 field-validation-errorfield-validation-valid 兩者具有相同的固定大小。 如此一來,欄位的顯示區域是靜態的,如果顯示錯誤訊息,就不會變更頁面流程。

驗證未直接來自使用者的資料

有時候,您必須驗證不直接來自 HTML 表單的資訊。 典型的範例是一個頁面,其中值會在查詢字串中傳遞,如下列範例所示:

http://server/myapp/EditClassInformation?classid=1022

在此案例中,您想要確定傳遞至頁面的值 (此處為 1022,) 的值 classid 有效。 您無法直接使用 Validation 協助程式來執行此驗證。 不過,您可以使用驗證系統的其他功能,例如顯示驗證錯誤訊息的能力。

注意

重要 請一律驗證您從 任何 來源取得的值,包括表單域值、查詢字串值和 Cookie 值。 人們很容易變更這些值, (可能因為惡意目的而) 。 因此,您必須檢查這些值,才能保護您的應用程式。

下列範例示範如何驗證傳入查詢字串中的值。 程式碼會測試值不是空的,而且它是整數。

if(!IsPost){
    if(!Request.QueryString["classid"].IsEmpty() && Request.QueryString["classid"].IsInt()) {
        // Process the value
    }
    else{
        Validation.AddFormError("No class was selected.");
    }
}

請注意,當要求不是表單提交 () if(!IsPost) 時,就會執行測試。 此測試會在第一次要求頁面時通過,但當要求是表單提交時則不會通過。

若要顯示此錯誤,您可以呼叫 Validation.AddFormError("message") ,將錯誤新增至驗證錯誤清單。 如果頁面包含方法的 Html.ValidationSummary 呼叫,就會在該處顯示錯誤,就像使用者輸入驗證錯誤一樣。

其他資源

在 ASP.NET Web Pages 網站中使用 HTML 表單