Добавление функции автодополнения к элементу управления TextBox

Применение технологий Ajax делает веб-приложения все более и более похожими на обычные настольные приложения. Одна из особенностей, которая имеется в некоторых настольных приложениях, но отсутствует в веб?приложениях, – это функция автодополнения. Когда в текстовое поле вводится некоторая информация, приложение отыскивает данные, подходящие для дополнения уже введенной информации (в большинстве броузеров, например, выводится список ранее веденных данных в аналогичные поля), и предлагает вариант заполнения поля.

Первым, самым известным веб?приложением, в котором появилась поддержка этой функции, стал сайт Google Suggest (http://www.google.com/webhp?complete=1&hl=en). Когда пользователь начинает ввод текста в поле, веб?страница предлагает наиболее популярные варианты строки поиска. Кроме того, страница показывает примерное количество результатов поиска по каждой из строк.

Теперь вы знаете, как это сделано: объект XMLHttpRequest обращается к веб?службе, которая возвращает возможные варианты строки поиска и предполагаемое число результатов.

Платформа ASP.NET AJAX предоставляет расширитель элемента управления AutoCompleteExtender, который используется именно для этих целей – поиск данных в фоновом режиме и представление этих данных в элементе формы.


При решении данной задачи для отображения подсказок и обеспечения возможности навигации по ним необходимо использовать каскадные таблицы стилей и программный код на JavaScript. Все это уже реализовано в расширителе из пакета Control Toolkit, а вам нужно лишь воспользоваться этими возможностями и создать веб?службу, которая будет возвращать данные. Однако следует заметить, что некоторые наиболее интересные особенности Google
Suggest (включая навигацию по списку с помощью клавиатуры) в расширителе реализованы не полностью.

С точки зрения веб?компонентов единственный элемент, для которого функция автодополнения имеет смысл, – это TextBox. Этот элемент демонстрируется в следующем фрагменте:
(asp:TextBox ID="vendor" runat="server")(/asp:TextBox)
Затем необходимо вставить элемент управления AutoCompleteExtender.

Этот элемент имеет несколько свойств, которые используются для настройки эффекта автодополнения. Наиболее важными из них являются следующие:
TargetControlID
Значение атрибута ID элемента управления, который должен быть дополнен функцией автодополнения
ServicePath
Путь к веб?службе, которая генерирует данные для автодополнения
ServiceMethod
Метод веб?службы, который вызывается для получения данных автодополнения
Ниже приводится пример разметки, в которой определяется расширитель:
(ajaxToolkit:AutoCompleteExtender runat="server"
ServicePath="Vendors.asmx" ServiceMethod="GetVendors"
TargetControlID="vendor" /)

В примере 12.3 демонстрируется страница ASP.NET с текстовым полем, который поддерживает возможность автодополнения.
Пример 12.3.


Добавление функции автодополнения к текстовому полю ввода AutoComplete.aspx
<%@ Page Language="C#" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit"
TagPrefix="ajaxToolkit" %>
"http://www.w3.org/TR/xhtml1/DTD/xhtml1?transitional.dtd"> ASP.NET AJAX

(body)
(asp:ScriptManager ID="ScriptManager1" runat="server")
(/asp:ScriptManager)
(asp:TextBox ID="vendor" runat="server")(/asp:TextBox)
onclick="window.alert('not implemented!');" />
(ajaxToolkit:AutoCompleteExtender runat="server"
ServicePath="Vendors.asmx" ServiceMethod="GetVendors"
TargetControlID="vendor" /)

(/body)


Кромет того, вам необходимо реализовать веб-службу, которая возвращала бы необходимые данные. Веб?служба должна включать метод с определенной сигнатурой, который будет вызываться расширителем.


Сигнатура метода приводится ниже:
public string[] (string prefixText, int count)

Метод принимает два параметра, назначение которых достаточно очевидно:
prefixText
Текст, введенный пользователем в текстовое поле, который будет использоваться в качестве префикса для всех совпадений
count
Максимальное число возвращаемых результатов

Данные должны возвращаться в виде массива строк, поэтому, к сожалению, вы не можете использовать наборы записей из базы данных или нечто похожее. В примере веб-службы для реализации функции автодополнения используется база данных AdventureWorks. В качестве результата клиенту возвращаются названия компаний всех производителей. Как обычно, вам придется адаптировать строку подключения под свои условия – в программном коде предполагается, что SQL Server 2005 Express Edition доступен с использованием типа аутентификации Windows и строкой подключения (local)\SQLEXPRESS.

Сначала программный код веб-службы проверяет строку поиска. Для простоты примера будем считать допустимыми только символы от a до z (верхнего и нижнего регистров). Эта проверка необходима для предотвращения инъекции SQL-?кода, потому что программа будет запускать поисковый запрос, содержащий выражение LIKE (подробнее об этом говорится во врезке «Внимание: опасайтесь инъекции SQL-кода»). В качестве альтернативы можно использовать параметризованные запросы.

Если для проверки входных данных используется регулярное выражение, желательно учитывать возможность появления символов, используемых в иностранных языках, таких как немецкие символы с умляутами или французские символы с диакритическими знаками. «Опасными» символами с точки зрения безопасности являются апострофы, кавычки, квадратные скобки, символ подчеркивания, двойной дефис, точка с запятой и знак процента. Эти символы (и их закодированные версии) имеют специальное значение в пределах запроса. Поэтому для проверки ввода пользователя лучше использовать методику белого списка (когда имеется предопределенный набор допустимых символов), а не черного списка (предопределенный набор недопустимых символов).

Веб-служба также будет проверять значение параметра count, передаваемого методу: оно должно быть положительным числом и не больше 100 (чтобы предотвратить возможность атак типа «отказ в обслуживании»).

Программный код веб?службы, выполняющий все эти проверки, выглядит примерно следующим образом:
using System.Text.RegularExpressions;
...
[WebMethod]
public string[] GetVendors(string prefixText, int count)
{
Regex regex = new Regex("^[a?zA?Z ]*$");
if (!regex.IsMatch(prefixText) || count < 1 || count > 100)
{
return null;
}

После проверки данных производится сборка SQL?запроса, который затем отправляется в базу данных. Типичный запрос выглядит следующим образом:
SELECT TOP 10 Name FROM Purchasing.Vendor WHERE NAME LIKE 'Int%'

Здесь предполагается, что параметр count имеет значение 10 (что фактически является значением по умолчанию, которое отправляет ASP.NET AJAX) и пользователь ввел строку Int в текстовое поле. Ниже приводится полный программный код, выполняющий SQL-запрос к базе данных, включая возврат результатов в виде множества записей:

SqlConnection conn = new SqlConnection(
"server=(local)\\SQLEXPRESS; Integrated Security=true; Initial
Catalog=AdventureWorks");
conn.Open( );
SqlCommand comm = new SqlCommand(
"SELECT TOP " +
count +
" Name FROM Purchasing.Vendor WHERE Name LIKE '" +
prefixText +
"%'",
conn);
SqlDataAdapter adap = new SqlDataAdapter(comm);
DataSet ds = new DataSet( );
adap.Fill(ds);

Далее данные необходимо преобразовать в массив строк. Этот массив должен содержать не более, чем count элементов (метод Math.Min() обеспечит возврат не более count элементов, даже если в базе данных имеется большее число записей).

Это легко можно сделать с помощью цикла for:
string[] vendors = new string[Math.Min(count, ds.Tables[0].Rows.Count)];
for (int i = 0; i < Math.Min(count, ds.Tables[0].Rows.Count); i++)
{
vendors[i] = ds.Tables[0].Rows[i].ItemArray[0].ToString( );
}
return vendors;
}

Полный программный код реализации этой веб?службы приводится в примере 12.4. Как говорилось в главах 1 и 5, чтобы платформа ASP.NET AJAX могла создать объект?посредник на Javascript для доступа к службе, необходимо использовать атрибут [ScriptService].
Пример 12.4. Веб-служба, которая возвращает возможные совпадения Vendors.asmx
<%@ WebService Language="C#" Class="Vendors" %>
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Data;
using System.Data.SqlClient;
using System.Text.RegularExpressions;
[WebService(Namespace = "http://hauser?wenz.de/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class Vendors : System.Web.Services.WebService
{
[WebMethod]
public string[] GetVendors(string prefixText, int count)
{
Regex regex = new Regex("^[a?zA?Z ]*$");
if (!regex.IsMatch(prefixText) || count < 1 || count > 100)
{
return null;
}
SqlConnection conn = new SqlConnection(
"server=(local)\\SQLEXPRESS; Integrated Security=true; Initial
Catalog=AdventureWorks");
conn.Open( );
SqlCommand comm = new SqlCommand(
"SELECT TOP " +
count +
" Name FROM Purchasing.Vendor WHERE Name LIKE '" +
prefixText +
"%'",
conn);
SqlDataAdapter adap = new SqlDataAdapter(comm);
DataSet ds = new DataSet( );
adap.Fill(ds);
string[] vendors = new string[Math.Min(count, ds.Tables[0].Rows.Count)];
for (int i = 0; i < Math.Min(count, ds.Tables[0].Rows.Count); i++)
{
vendors[i] = ds.Tables[0].Rows[i].ItemArray[0].ToString( );
}
return vendors;
}
}

Теперь посмотрим, как выглядят результаты в броузере. Загрузите страницу и введите несколько символов – не меньше трех (ASP.NET AJAX не будет отправлять запрос веб?службе при меньшем числе символов). Если совпадения будут найдены, они появятся в текстовом поле с некоторой задержкой.

Если поиск не дал результатов, попробуйте следующее: в базе данных имеется несколько компаний, названия которых начинаются со слова «International», поэтому после ввода этого слова вы должны получить несколько совпадений.

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела ASP.NET AJAX на эту тему:
Борьба со спамом в блогах и других формах ввода информации
Динамическая свертка единственной панели
Отображение всплывающего окна на странице
Присоединение календаря к текстовому полю
Создание интерфейса с вкладками