Cómo: Convertir en números datos numéricos proporcionados por el usuario en controles web

Actualización: noviembre 2007

Dado que una página web se puede mostrar en cualquier parte del mundo, los usuarios pueden proporcionar datos numéricos en un control TextBox en un número casi ilimitado de formatos. Por tanto, es muy importante determinar la configuración regional y la referencia cultural del usuario de la página web. Cuando analice los datos proporcionados por el usuario, puede aplicar las convenciones de formato definidas por la configuración regional y la referencia cultural del usuario.

Para convertir la entrada numérica de un control web TextBox en un número

  1. Determine si la matriz de cadenas devuelta por la propiedad HttpRequest.UserLanguages contiene elementos. Si no es así, continúe en el paso 6.

  2. Si la matriz de cadenas devuelta por la propiedad UserLanguages contiene elementos, recupere el primer elemento. El primer elemento indica el idioma y la región predeterminados o preferidos por el usuario.

  3. Cree una instancia de un objeto CultureInfo que represente la referencia cultural preferida del usuario; para ello, llame al constructor CultureInfo.CultureInfo(String, Boolean).

  4. Llame al método TryParse o Parse del tipo numérico en el que desea convertir la entrada del usuario. Utilice una sobrecarga del método TryParse o Parse con un parámetro provider y pásele cualquiera de los elementos siguientes:

  5. Si la conversión no se realiza correctamente, repita los pasos 2 al 4 en cada elemento restante de la matriz de cadenas devuelta por la propiedad UserLanguages.

  6. Si la conversión sigue produciendo errores o si la matriz de cadenas devuelta por la propiedad UserLanguages está vacía, analice la cadena usando la referencia cultural de todos los idiomas devuelta por la propiedad CultureInfo.InvariantCulture.

Ejemplo

El ejemplo siguiente corresponde a la página completa de código subyacente de un formulario web en la que se pide al usuario que escriba un valor numérico en un control TextBox y se convierte en un número. Ese número se duplica y se muestra a continuación utilizando las mismas reglas de formato que la entrada original.

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));
      }
   }
}

La propiedad HttpRequest.UserLanguages se rellena a partir de los nombres de la referencia cultural incluidos en los encabezados Accept-Language de una solicitud HTTP. Sin embargo, no todos los exploradores incluyen encabezados Accept-Language en sus solicitudes y además los usuarios pueden suprimir los encabezados por completo. Por ello, es importante tener una referencia cultural de reserva al analizar los datos proporcionados por el usuario. Por lo general, la referencia cultural de reserva es la referencia cultural de todos los idiomas devuelta por la propiedad CultureInfo.InvariantCulture. Los usuarios también pueden proporcionar a Internet Explorer nombres de la referencia cultural escribiéndolos en un cuadro de texto, de modo que es posible que los nombres de la referencia cultural no sean válidos. Por todo esto, es importante utilizar el control de excepciones al crear instancias de un objeto CultureInfo.

Cuando se recupera de una solicitud HTTP enviada por Internet Explorer, la matriz HttpRequest.UserLanguages se rellena en orden de preferencia del usuario. El primer elemento de la matriz contiene el nombre de la referencia cultural o región primaria del usuario. Si la matriz contiene algún otro elemento, Internet Explorer le asigna arbitrariamente un especificador de calidad, que está delimitado del nombre de la referencia cultural mediante un punto y coma. Por ejemplo, una entrada para la referencia cultural fr-FR podría tener la forma fr-FR;q=0.7.

En el ejemplo, se llama al constructor CultureInfo con el parámetro useUserOverride establecido en false para crear un nuevo objeto CultureInfo. De este modo, tiene la seguridad de que si el nombre de la referencia cultural es el nombre de la referencia cultural predeterminada del servidor, el nuevo objeto CultureInfo creado por el constructor de clase contiene la configuración predeterminada de una referencia cultural y no refleja las configuraciones invalidadas con la aplicación Configuración regional y de idioma del servidor. Es poco probable que los valores de una configuración invalidada en el servidor permanezcan en el sistema del usuario o se reflejen en los datos proporcionados por el usuario.

Su código puede llamar al método Parse o TryParse del tipo numérico en el que se convertirá la entrada del usuario. Puede ser necesario llamar varias veces a un método de análisis en una única operación de análisis. Como resultado, el método TryParse resulta más conveniente porque devuelve false si se producen errores en una operación de análisis. Por el contrario, mantener un control sobre las excepciones repetidas que puede producir el método Parse puede ser una tarea excesivamente costosa cuando se trata de una aplicación web.

Compilar el código

Para compilar el código, cópielo en una página de código subyacente de ASP.NET para que reemplace todo el código existente. La página web de ASP.NET debe contener los controles siguientes:

  • Un control Label, al que no se hace referencia en código. Establezca la propiedad Text en "Escriba un número:".

  • Un control TextBox denominado NumericString.

  • Un control Button denominado OKButton. Establezca la propiedad Text en "Aceptar".

Cambie el nombre de la clase de NumericUserInput por el nombre de la clase definido por el atributo Inherits de la directiva Page de la página de ASP.NET. Cambie el nombre de la referencia del objeto NumericInput por al nombre definido en el atributo id de la etiqueta form de la página de ASP.NET.

Seguridad

Para evitar que un usuario inserte el script en la secuencia HTML, los datos proporcionados por el usuario nunca deberían devolverse directamente en la respuesta del servidor. En su lugar, deberían codificarse con el método HttpServerUtility.HtmlEncode.

Vea también

Conceptos

Temas "Cómo..." sobre formatos

Analizar cadenas numéricas