HOW TO:將使用者輸入 Web 控制項的數值轉換成數字
由於網頁可在任何地方顯示,因此使用者可在 TextBox 控制項中輸入幾乎無限多種格式的數值。 所以,務必決定網頁使用者的地區設定和文化特性。 當您剖析使用者輸入時,就可以接著套用使用者地區設定和文化特性定義的格式化慣例。
將 Web TextBox 控制項的數值輸入轉換成數字
判斷 HttpRequest.UserLanguages 屬性傳回的字串陣列是否已填入。 如果尚未填入,則繼續進行步驟 6。
如果 UserLanguages 屬性所傳回的字串陣列已填入,就會擷取它的第一個項目。 第一個項目指出使用者的預設或慣用的語言和區域。
呼叫 CultureInfo.CultureInfo(String, Boolean) 建構函式以具現化 CultureInfo 物件,此物件代表使用者慣用的文化特性。
呼叫要將使用者輸入轉換成之數值型別的 TryParse 或 Parse 方法。 使用 TryParse 或 Parse 方法的多載與 provider 參數,並將下列任一項傳遞給該多載:
在步驟 3 中建立的 CultureInfo 物件。
在步驟 3 中所建立 CultureInfo 物件的 NumberFormat 屬性傳回的 NumberFormatInfo 物件。
如果轉換失敗,則針對 UserLanguages 屬性傳回的字串陣列中其餘每一個項目重複步驟 2 到 4。
如果轉換還是失敗,或者,如果 UserLanguages 屬性所傳回的字串陣列為空白,請使用由 CultureInfo.InvariantCulture 屬性所傳回的 Invariant 文化特性 (不因文化特定而異) 來剖析字串。
範例
以下範例是 Web Form 的完整程式碼後置頁,會要求使用者在 TextBox 控制項中輸入數值,並將它轉換成數字。 接著該數字會加倍,並且使用與原始輸入相同的格式化規則顯示。
Imports System.Globalization
Partial Class NumericUserInput
Inherits System.Web.UI.Page
Protected Sub OKButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles OKButton.Click
Dim locale As String
Dim culture As CultureInfo = Nothing
Dim number As Double
Dim result As Boolean
' Exit if input is absent.
If String.IsNullOrEmpty(Me.NumericString.Text) Then Exit Sub
' Hide form elements.
Me.NumericInput.Visible = False
' Get user culture/region
If Not (Request.UserLanguages.Length = 0 OrElse String.IsNullOrEmpty(Request.UserLanguages(0))) Then
Try
locale = Request.UserLanguages(0)
culture = New CultureInfo(locale, False)
' Parse input using user culture.
result = Double.TryParse(Me.NumericString.Text, NumberStyles.Any, culture.NumberFormat, number)
Catch
End Try
' If parse fails, parse input using any additional languages.
If Not result Then
If Request.UserLanguages.Length > 1 Then
For ctr As Integer = 1 To Request.UserLanguages.Length - 1
Try
locale = Request.UserLanguages(ctr)
' Remove quality specifier, if present.
locale = Left(locale, InStr(locale, ";") - 1)
culture = New CultureInfo(Request.UserLanguages(ctr), False)
result = Double.TryParse(Me.NumericString.Text, NumberStyles.Any, culture.NumberFormat, number)
If result Then Exit For
Catch
End Try
Next
End If
End If
End If
' If parse operation fails, use invariant culture.
If Not result Then
result = Double.TryParse(Me.NumericString.Text, NumberStyles.Any, CultureInfo.InvariantCulture, number)
End If
' Double result
number *= 2
' Display result to user.
If result Then
Response.Write("<P />")
Response.Write(Server.HtmlEncode(Me.NumericString.Text) + " * 2 = " + number.ToString("N", culture) + "<BR />")
Else
' Unhide form.
Me.NumericInput.Visible = True
Response.Write("<P />")
Response.Write("Unable to recognize " + Server.HtmlEncode(Me.NumericString.Text))
End If
End Sub
End Class
using System;
using System.Globalization;
partial class NumericUserInput : System.Web.UI.Page
{
protected void OKButton_Click(object sender, EventArgs e)
{
string locale;
CultureInfo culture = null;
double number = 0;
bool result = false;
// Exit if input is absent.
if (String.IsNullOrEmpty(this.NumericString.Text)) return;
// Hide form elements.
this.NumericInput.Visible = false;
// Get user culture/region
if (!(Request.UserLanguages.Length == 0 || String.IsNullOrEmpty(Request.UserLanguages[0])))
{
try
{
locale = Request.UserLanguages[0];
culture = new CultureInfo(locale, false);
// Parse input using user culture.
result = Double.TryParse(this.NumericString.Text, NumberStyles.Any,
culture.NumberFormat, out number);
}
catch { }
// If parse fails, parse input using any additional languages.
if (!result)
{
if (Request.UserLanguages.Length > 1)
{
for (int ctr = 1; ctr <= Request.UserLanguages.Length - 1; ctr++)
{
try
{
locale = Request.UserLanguages[ctr];
// Remove quality specifier, if present.
locale = locale.Substring(1, locale.IndexOf(';') - 1);
culture = new CultureInfo(Request.UserLanguages[ctr], false);
result = Double.TryParse(this.NumericString.Text, NumberStyles.Any, culture.NumberFormat, out number);
if (result) break;
}
catch { }
}
}
}
}
// If parse operation fails, use invariant culture.
if (!result)
result = Double.TryParse(this.NumericString.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out number);
// Double result.
number *= 2;
// Display result to user.
if (result)
{
Response.Write("<P />");
Response.Write(Server.HtmlEncode(this.NumericString.Text) + " * 2 = " + number.ToString("N", culture) + "<BR />");
}
else
{
// Unhide form.
this.NumericInput.Visible = true;
Response.Write("<P />");
Response.Write("Unable to recognize " + Server.HtmlEncode(this.NumericString.Text));
}
}
}
HttpRequest.UserLanguages 屬性會從 HTTP 要求所包含 Accept-Language 標頭中的文化特性名稱填入。 不過,並非所有瀏覽器的要求都包含 Accept-Language 標頭,而且使用者可以完全隱藏標頭。 因此,剖析使用者輸入時務必有後援文化特性。 通常後援文化特性是 CultureInfo.InvariantCulture 傳回的不因國別而異的文化特性。 使用者也可以將文字方塊中輸入的文化特性名稱提供給 Internet Explorer,如此可能讓文化特性名稱無效。 因此具現化 CultureInfo 物件時,務必使用例外處理。
從 Internet Explorer 提交的 HTTP 要求擷取時,HttpRequest.UserLanguages 陣列會依使用者偏好設定填入。 陣列中的第一個項目包含使用者主要文化特性/區域的名稱。 如果陣列包含任何額外的項目,Internet Explorer 會為這些項目指派任意限定規範,並且使用分號與文化特性名稱分隔。 例如,fr-FR 文化特性的項目可能採用這個格式 fr-FR;q=0.7。
範例會呼叫 CultureInfo 建構函式,且其 useUserOverride 參數會設為 false,以建立新的 CultureInfo 物件。 如此可確定,如果文化特性名稱是伺服器上預設的文化特性名稱,則類別建構函式建立的 CultureInfo 物件會包含文化特性的預設設定,並且不會反映使用伺服器的 [地區及語言選項] 應用程式覆寫的任何設定。 伺服器上任何覆寫設定的值都不會出現在使用者的系統上,或是反映在使用者輸入中。
您的程式碼可以呼叫使用者輸入將轉換成的數值型別之 Parse 或 TryParse 方法。 您可能需要針對單一剖析作業重複呼叫剖析方法。 因此 TryParse 方法可能較佳,因為它會在剖析作業失敗時傳回 false。 相反地,對於 Web 應用程式而言,處理 Parse 方法可能擲回的重複例外狀況可能是相當耗費資源的方法。
編譯程式碼
若要編譯程式碼,請將它複製到 ASP.NET 程式碼後置頁,以取代所有現有的程式碼。 ASP.NET 網頁應包含下列控制項:
名為 NumericString 的 TextBox 控制項。
將類別的名稱從 NumericUserInput 變更為 ASP.NET 頁面之 Page 指示詞的 Inherits 屬性所定義的類別名稱。 接著,將 NumericInput 物件參考的名稱變更為 ASP.NET 頁面之 form 標記的 id 屬性所定義的名稱。
安全性
為避免使用者將指令碼插入 HTML 資料流中,絕不可將使用者輸入直接回應 (Echo) 至伺服器回應中。 而是使用 HttpServerUtility.HtmlEncode 方法將使用者輸入編碼。