Postupy: Převod číselného uživatelského vstupu ve webových ovládacích prvcích na čísla
Protože webovou stránku lze zobrazit kdekoli na světě, uživatelé mohou vložit číselná data do ovládacího prvku TextBox v téměř neomezeném počtu formátů. V důsledku je velmi důležité určit národní prostředí a jazykovou verzi uživatele webové stránky. Když analyzujete vstup uživatele, pak můžete použít formátující konvence definované národním prostředím a jazykovou verzí uživatele.
Chcete-li převést číselný vstup z ovládacího prvku webového textového pole na číslo
Určete, zda je naplněno pole řetězců vrácené vlastností HttpRequest.UserLanguages. Pokud tomu tak není, pokračujte krokem 6.
Pokud je naplněno pole řetězců vrácené vlastností UserLanguages, načtěte jeho první prvek. První prvek označuje výchozí nastavení uživatele nebo preferovaný jazyk a oblast.
Vytvořte instanci objektu CultureInfo, který představuje preferovanou jazykovou verzi uživatele voláním konstruktoru CultureInfo.CultureInfo(String, Boolean).
Volejte buď metodu TryParse nebo Parse číselného typu, na který chcete převést uživatelský vstup. Použijte přetížení metody TryParse nebo Parse s parametrem provider a předejte ji jakékoli z následujících:
Objekt CultureInfo vytvořený v kroku 3.
Objekt NumberFormatInfo, který je vrácený vlastností NumberFormat objektu CultureInfo vytvořeného v kroku 3.
Pokud převod selže, opakujte kroky 2 až 4 pro každý zbývající element v poli řetězců vráceného vlastností UserLanguages.
Pokud se převod stále nedaří, nebo pokud je pole řetězců vrácené vlastností UserLanguages prázdné, analyzujte řetězec pomocí invariantní jazykové verze, která je vrácená vlastností CultureInfo.InvariantCulture.
Příklad
Následující příklad je kompletní stránka s kódem v pozadí pro webový formulář, který žádá uživatele, aby zadal číselnou hodnotu v ovládacím prvku TextBox a převede ji na číslo. Toto číslo se pak zdvojnásobí a zobrazí pomocí stejných pravidel formátování jako původní vstup.
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));
}
}
}
Vlastnost HttpRequest.UserLanguages je naplněna z názvů jazykových verzí, které jsou obsaženy v záhlaví Accept-Language, které jsou součástí požadavku HTTP. Ne všechny prohlížeče však ve svých požadavcích zahrnují záhlaví Accept-Language a uživatelé mohou také potlačit záhlaví úplně. Díky tomu je důležité mít náhradní jazykovou verzi při analýze vstupu uživatele. Obvykle je náhradní jazyková verze invariantní jazyková verze vrácená CultureInfo.InvariantCulture. Uživatelé mohou také poskytovat Internet Explorer s názvy jazykových verzí, které vložili do textového pole, které vytvoří tu možnost, že názvy jazykových verzí mohou být neplatné. Proto je důležité použít zpracování výjimek při vytvoření instance objektu CultureInfo.
Při načítání z odeslaných HTTP požadavků Internet Explorerem je pole HttpRequest.UserLanguages naplněno v pořadí podle předvolby uživatele. První prvek pole obsahuje název primární jazykové verze/oblasti uživatele. Pokud pole obsahuje jakékoli další položky, Internet Explorer jim libovolně přiřadí specifikátor kvality, který je oddělen středníkem od názvu jazykové verze. Například položka pro jazykovou verzi fr-FR může mít formu fr-FR;q=0.7.
Příklad volá konstruktor CultureInfo s jeho parametrem useUserOverride nastaveným false pro vytvoření nového objektu CultureInfo. To zajišťuje, že pokud je název jazykové verze výchozím názvem jazykové verze na serveru, pak nový objekt CultureInfo vytvořený pomocí konstruktoru třídy obsahuje výchozí nastavení jazykové verze a neprojeví se žádné nastavení přepsané použitím aplikace serveru Místní a jazykové nastavení. Je nepravděpodobné, že v uživatelském systému existují hodnoty z jakéhokoli přepsaného nastavení na serveru, nebo že se projeví v uživatelském vstupu.
Váš kód může volat buď metodu Parse nebo TryParse číselného typu, na který bude převeden uživatelský vstup. Mohou být vyžadována opakovaná volání metody analýzy pro jedinou operaci analýzy. Ve výsledku je metoda TryParse lepší, protože vrátí false v případě selhání operace analýzy. Naopak ošetření opakovaných výjimek, které mohou být vývolány metodou Parse může být velmi drahým rešením ve Webové aplikaci.
Probíhá kompilace kódu
Pro kompilaci kódu jej zkopírujte do stránky s kódem v pozadí ASP.NET tak, že nahradí celý existující kód. Webová stránka ASP.NET by měla obsahovat následující ovládací prvky:
Ovládací prvek Label, na který není odkaz v kódu. Nastavte jeho vlastnost Text na "Enter a Number:".
Ovládací prvek TextBox s názvem NumericString.
Ovládací prvek Button s názvem OKButton. Nastavte jeho vlastnost Text na OK.
Změňte název třídy z NumericUserInput na název třídy, který je definován atributem Inherits stránky ASP.NET direktivou Page. Změňte název odkazu objektu NumericInput na název definován atributem id stránky ASP.NET se značkou form.
Zabezpečení
Chcete-li zabránit uživateli ve vložení skriptu do HTML proudu, uživatelský vstup by neměl být nikdy přímo vpisován zpět v odpovědi serveru. Místo toho by měl být kódován pomocí metody HttpServerUtility.HtmlEncode.