How to: Convert Numeric User Input in Web Controls to Numbers
Because a Web page can be displayed anywhere in the world, users can input numeric data into a TextBox control in an almost unlimited number of formats. As a result, it is very important to determine the locale and culture of the Web page's user. When you parse user input, you can then apply the formatting conventions defined by the user's locale and culture.
To convert numeric input from a Web TextBox control to a number
Determine whether the string array returned by the HttpRequest.UserLanguages property is populated. If it is not, continue to step 6.
If the string array returned by the UserLanguages property is populated, retrieve its first element. The first element indicates the user's default or preferred language and region.
Call either the TryParse or the Parse method of the numeric type that you want to convert the user's input to. Use an overload of the TryParse or the Parse method with a provider parameter, and pass it either of the following:
If the conversion fails, repeat steps 2 through 4 for each remaining element in the string array returned by the UserLanguages property.
If the conversion still fails or if the string array returned by the UserLanguages property is empty, parse the string by using the invariant culture, which is returned by the CultureInfo.InvariantCulture property.
The following example is the complete code-behind page for a Web form that asks the user to enter a numeric value in a TextBox control and converts it to a number. That number is then doubled and displayed by using the same formatting rules as the original input.
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
The HttpRequest.UserLanguages property is populated from the culture names that are contained in Accept-Language headers included in an HTTP request. However, not all browsers include Accept-Language headers in their requests, and users can also suppress the headers completely. This makes it important to have a fallback culture when parsing user input. Typically, the fallback culture is the invariant culture returned by CultureInfo.InvariantCulture. Users can also provide Internet Explorer with culture names that they input in a text box, which creates the possibility that the culture names may not be valid. This makes it important to use exception handling when instantiating a CultureInfo object.
When retrieved from an HTTP request submitted by Internet Explorer, the HttpRequest.UserLanguages array is populated in order of user preference. The first element in the array contains the name of the user's primary culture/region. If the array contains any additional items, Internet Explorer arbitrarily assigns them a quality specifier, which is delimited from the culture name by a semicolon. For example, an entry for the fr-FR culture might take the form fr-FR;q=0.7.
The example calls the CultureInfo constructor with its useUserOverride parameter set to false to create a new CultureInfo object. This ensures that, if the culture name is the default culture name on the server, the new CultureInfo object created by the class constructor contains a culture's default settings and does not reflect any settings overridden by using the server's Regional and Language Options application. The values from any overridden settings on the server are unlikely to exist on the user's system or to be reflected in the user's input.
Your code can call either the Parse or the TryParse method of the numeric type that the user's input will be converted to. Repeated calls to a parse method may be required for a single parsing operation. As a result, the TryParse method is better, because it returns false if a parse operation fails. In contrast, handling the repeated exceptions that may be thrown by the Parse method can be a very expensive proposition in a Web application.
To compile the code, copy it into an ASP.NET code-behind page so that it replaces all the existing code. The ASP.NET Web page should contain the following controls:
A TextBox control named NumericString.
Change the name of the class from NumericUserInput to the name of the class that is defined by the Inherits attribute of the ASP.NET page's Page directive. Change the name of the NumericInput object reference to the name defined by the id attribute of the ASP.NET page's form tag.
To prevent a user from injecting script into the HTML stream, user input should never be directly echoed back in the server response. Instead, it should be encoded by using the HttpServerUtility.HtmlEncode method.