Практическое руководство. Преобразование числовых данных, введенных пользователем в веб-элементах управления, в числа

Поскольку веб-страница может отображаться в любой части мира, пользователи могут вводить числовые данные в элемент управления TextBox, используя почти неограниченное число форматов. Поэтому очень важно определить языковой стандарт и региональные параметры пользователя веб-страницы. При разборе данных, введенных пользователем, можно применить соглашения форматирования, определенные языковым и региональными параметрами пользователя.

Преобразование входных числовых данных из веб-элемента управления TextBox в число

  1. Определите, заполняется ли массив строк, возвращаемый свойством HttpRequest.UserLanguages. Если это не так, то перейдите к шагу 6.

  2. Если массив строк, возвращаемый свойством UserLanguages заполнен, то извлеките его первый элемент. Первый элемент указывает на язык и регион по умолчанию или выбранный пользователем.

  3. Создайте объект CultureInfo, представляющий выбранные пользователем региональные параметры, путем вызова конструктора CultureInfo.CultureInfo(String, Boolean).

  4. Вызовите метод TryParse или метод Parse числового типа, к которому требуется преобразовать введенные пользователем данные. Используйте перегрузку метода TryParse или Parse с параметром provider и передайте ему один из следующих объектов:

  5. Если выполнить преобразование не удалось, повторите шаги со второго по четвертый для каждого оставшегося элемента в массиве строк, возвращаемого свойством UserLanguages.

  6. Если преобразование по-прежнему не удается или массив строк, возвращаемый свойством UserLanguages пуст, произведите разбор строки с использованием инвариантных региональных параметров, которые возвращаются свойством CultureInfo.InvariantCulture.

Пример

Следующий пример представляет собой полную страницу фонового кода для веб-формы, в которой пользователю предлагается ввести числовое значение в элемент управления 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 заполняется на основании имен региональных параметров, содержащихся в заголовках Accept-Language, включенных в HTTP-запрос. Однако не все обозреватели включают заголовки Accept-Language в свои запросы, кроме того, пользователи могут полностью запретить заголовки. В связи с этим при разборе данных, введенных пользователем, возникает необходимость иметь резервный набор региональных параметров. Обычно, резервный набор региональных параметров является инвариантным и возвращается свойством CultureInfo.InvariantCulture. Пользователи также могут ввести в Internet Explorer название языка и региональных параметров, которое они вводят в текстовое поле, а это создает вероятность того, что такое название может оказаться недопустимым. Всвязи с этим возникает необходимость обработки исключений при создании объекта CultureInfo.

При извлечении из HTTP-запроса, посланного Internet Explorer, массив HttpRequest.UserLanguages заполняется в порядке, определенном в пользовательских настройках. Первый элемент массива содержит название основного национального языка/региона пользователя. Если массив содержит другие элементы, то Internet Explorer произвольно назначит им спецификатор качества, который отделяется от имени региональных параметров точкой с запятой. Например, запись региональных параметров fr-FR может принять форму fr-FR;q=0.7.

В примере вызывается конструктор CultureInfo с параметром useUserOverride с настройкой falseдля создания нового объекта CultureInfo. В этом случае, если региональные параметры по умолчанию используются на сервере, то новый объект CultureInfo, созданный конструктором класса, содержит все региональные параметры по умолчанию и не зависит от настроек, заданных при помощи серверного приложения Язык и региональные параметры. Значения всех скорректированных настроек на сервере вряд ли появятся на компьютере пользователя или отразятся в данных, введенных пользователем.

Код может вызвать метод Parse или метод TryParse числового типа, к которому требуется преобразовать данные, введенные пользователем. Для отдельной операции разбора может потребоваться повторный вызов метода синтаксического анализа. В результате метод TryParse является более эффективным, поскольку он возвращает false при отказе операции синтаксического анализа. Напротив, обработка повторяющихся исключений, которые могут посылаться методом Parse, может быть слишком затратной для веб-приложений.

Компиляция кода

Чтобы скомпилировать код, скопируйте его в страницу фонового кода ASP.NET таким образом, чтобы он заменил весь существующий код. Веб-страница ASP.NET должна содержать следующие элементы управления:

  • Элемент управления Label, который не указан в коде. Присвойте его свойству Text значение "Введите число:".

  • Элемент управления TextBox с именем NumericString.

  • Элемент управления Button с именем OKButton. Присвойте его свойству Text значение "ОК".

Измените имя класса с NumericUserInput на имя класса, который определен атрибутом Inherits директивы Page страницы ASP.NET. Измените имя ссылки на объект NumericInput на имя, определенное атрибутом id тега form страницы ASP.NET.

Безопасность

Чтобы предостеречь пользователя от добавления скрипта в поток HTML, вводимые пользователем данные никогда не должны непосредственно передаваться обратно в ответе сервера. Вместо этого они должны быть зашифрованы с помощью метода HttpServerUtility.HtmlEncode.

См. также

Основные понятия

Выполнение операций форматирования

Разбор числовых строк