Современные веб-технологии

Применение поисковых технологий в Интернет-магазине

Разбить на страницы
Показывать лекцию целиком

Цель практического занятия: В Internet Explorer 7 появилась возможность выполнять быстрый поиск через специальную панель. В Internet Explorer 8 возможности такого быстрого поиска были расширены, за счет добавления визуальных возможностей и изменения шаблона отображения. Целью данного семинара является рассмотрение технологии разработки собственного поискового расширение для Интернет-магазина, опираясь на стандарт OpenSearch.

Файлы к практическому занятию Вы можете скачать здесь.

21.1. Архитектура

OpenSearch – набор технологий, позволяющих веб-сайтам и поисковым системам публиковать результаты поиска в форматах, удобных для распространения и сбора.

OpenSearch был разработан A9, дочерней компанией Amazon.com. Первая версия, OpenSearch 1.0, была представлена на конференции, посвященной Web 2.0 в марте 2005 года. Черновые версии OpenSearch 1.1 были опубликованы в сентябре и декабре 2005 года. Спецификация OpenSearch лицензирована компанией A9 по Creative Commons Attribution-ShareAlike 2.5 License.

В OpenSearch входят:

  • XML -файлы с описанием поисковой системы;
  • стандартизованный синтаксис запросов, описывающий, где и как получать результаты поиска;
  • RSS (в OpenSearch 1.0) или более общий OpenSearch -ответ (в OpenSearch 1.1) – форматы, предоставляющие поисковые результаты;
  • OpenSearch -агрегаторы – сайты, позволяющие отображать OpenSearch -результаты;
  • элементы на веб-странице для автоматического обнаружения пользовательским клиентом возможности использования OpenSearch на данном сайте.
  • Версия 1.0 спецификации позволяла предоставлять результаты поисковых запросов только в формате RSS, в то время как версия 1.1 позволяет использовать RSS и Atom – единственные форматы, формально поддерживаемые OpenSearch -агрегаторами, но и другие типы вполне допустимы, например, HTML.

    21.2. Поисковые системы и ПО, поддерживающие OpenSearch

    К поисковым системам и программному обеспечению, поддерживающему OpenSearch относятся:

  • Википедия предлагает статьи, соответствующие введенной строке;
  • Mozilla Firefox версии 2 и выше позволяет интегрировать поисковые системы, поддерживающие OpenSearch, со своей панелью поиска;
  • Internet Explorer версии 7 и выше так же позволяет добавлять OpenSearch -системы.
  • Функция Search Suggestions (поисковые подсказки) предлагает пользователю по мере ввода им информации подходящие варианты, соответствующие вводимому запросу. Это очень удобно, если неизвестно, как правильно пишется чье-то имя, или как полностью называется организация. Многие сайты, такие как yandex.ru или google.com предоставляют данную функцию, использую формат JSON. При этом IE8 также поддерживает JSON suggestions.

    В IE8 возможности функции расширены за счет добавления графических подсказок. На рис.21.1 можно видеть текстовые подсказки графические подсказки с Amazon.com.

    (рис 21.1) Графические подсказки поискового расширения сайта Amazon.com

    Некоторые из подсказок включают дополнительный текст, выделенный серым курсивом. Он лишь описывает результаты запроса. Это позволяет принять осмысленное решение о том, какой из результатов наиболее полно соответствует запросу. Более того поисковые провайдеры могут добавлять дополнительные разделители к подсказкам. Так, к примеру, и eBay и The New York Times реализовали разделители, отделяющие товары от различного рода публикаций (рис.21.2).

    (рис 21.2) Пример разделителей поискового расширения сайта eBay

    21.2.1. Пример поиска на Википедии

    Как пример, рассмотрим поисковое расширение, поставляемое сайтом Wikipedia.org. При переходе на любую страницу англоязычной Википедии, кнопка выбора поиска меняет свой цвет, показывая, что данный сайт предоставляет свое расширение (рис.21.3).

    (рис 21.3) Уведомление пользователя о том, что текущий сайт содержит поисковый провайдер

    После установки расширения, у пользователя появляется возможность мгновенно искать информацию по Википедии, находясь на любом другом сайте. Так, при вводе запроса Moscow можно наблюдать результат, показанный на рис.21.4.

    (рис 21.4) Пример поискового расширения сайта Wikipedia.org

    Видно, что для каждой найденной страницы отображается ее название, краткое описание и в тех случаях, когда это возможно, картинка. Аналогичное поисковое расширение мы разработаем и для нашего Интернет-магазина.

    21.3. Создание поисковой страницы

    Прежде чем приступать к разработке поискового расширения для IE необходимо создать страницу (или набор страниц и сервисов) для поиска в нашем Интернет-магазине. Для этого добавим в папку Products еще одну страницу – ProductsSearch.aspx и скопируем ASP-код для левого PlaceHolder 'а из products/default.aspx. Удалим обработчик выбора строки, так как сейчас нас интересует только сам поиск, а не просмотр результатов. В бэк-коде реализуем метод Page_Load следующим образом:

    GridViewProducts.DataKeyNames = new string[]
      {
        "ProductID"
      };
    
    ProductsLinqDataSource.Where = "";
    ProductsLinqDataSource.WhereParameters.Clear();
    if (!string.IsNullOrEmpty(Request.QueryString["query"]))
    {
      ProductsLinqDataSource.Where = "Name.Contains(@query)";
      ProductsLinqDataSource.WhereParameters.Add("query", DbType.String, 
                                            Request.QueryString["query"]);
    }

    Этот код похож на тот, что мы писали при разработке страницы products/default.aspx, однако здесь, вместо ограничения категории или подкатегории продуктов мы задаем фильтр на название продукта. При выполнении запроса LINQ преобразует код "Name.Contains(@query)" примерно в следующий SQL запрос:

    Where Name Like '%@query%'
    Примечание: здесь метод Contains – это метод класса string, проверяющий на вхождение переданной в параметре строки в строку Name. В общем случае здесь же необходимо проверить query на null, иначе null будет трактоваться как object и метод string.Contains(object o) не будет найден. Один из самых простых вариантов – добавить в конце строчку:
    ProductsLinqDataSource.WhereParameters[0].ConvertEmptyStringToNull = false;
    Примечание: в идеале на страницу стоит добавить текстовое поле и кнопку, при нажатии на которую и будет происходить поиск товара, но в данном случае мы разрабатываем страницу, которая будет открываться при поиске через сам браузер.

    Параметр поиска будет передаваться через запрос, и называться query. Проверим разработанную страницу, поискав все продукты, содержащие в названии ' bike '.

    Для этого обратимся по адресу http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=bike (рис.21.5).

    (рис 21.5) Страница поиска интернет-магазина Adventure Works

    21.4. Создание файла описания поискового расширения

    Теперь необходимо разработать само поисковое расширение. Как уже отмечалось, это небольшой файл в формате xml.

    21.4.1. Структура и формат файла описания OpenSearch

    Файлы описания OpenSearch – это небольшие XML -файлы, содержащие описание поставщика поиска для браузера Internet Explorer 8. В табл. 21.1 описываются значения, используемые в файле описания OpenSearch.

    Файл описания OpenSearch
    Значение Описание
    ShortName (обязательный параметр) Имя поставщика поиска, отображаемое при выборе поставщика в поле мгновенного поиска.
    URL (обязательный параметр) URL-адрес для основных поисковых запросов поставщика. Необходимо указывать абсолютный URL-адрес.
    Image (необязательный параметр) Указатель на файл значка, связанного с поставщиком поиска на веб-сайте. Этот значок отображается рядом с именем поставщика в поле мгновенного поиска. Если не указан допустимый файл значка ярлыка, используется общий значок.
    Suggestions URL ( JSON ) (необязательный параметр) URL-адрес, по которому могут быть извлечены варианты поиска с использованием нотации объектов JavaScript ( JSON ).
    Suggestions URL ( XML ) (необязательный параметр) URL-адрес, по которому могут быть извлечены варианты поиска в формате XML.
    PreviewUrl (необязательный параметр) URL-адрес для отображения результатов в окне предварительного просмотра ускорителя.

    Ниже приведен образец файла описания OpenSearch, в котором определяется тип предоставляемых поисковых служб:

    <?xml version="1.0" encoding="UTF-8"?>
    <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" 
                           xmlns:ie="http://schemas.microsoft.com/Search/2008/">
      <ShortName>My Custom Search</ShortName>
      <Image height="16" width="16" type="image/icon">
         http://example.com/example.ico
      </Image>
      <Url type="text/html" 
           template="http://example.com/search.aspx?q={searchTerms}amp;source=IE"/>
      <Url type="application/x-suggestions+json" 
           template="http://suggestions.example.com/search.aspx?q={searchTerms}"/>
      <Url type="application/x-suggestions+xml" 
           template="http://suggestions.example.com/search.aspx?q={searchTerms}"/>
      <ie:PreviewUrl type="text/html" 
           template="http://suggestions.example.com/search.aspx?q={searchTerms}"/>
    </OpenSearchDescription>

    Каждый файл описания OpenSearch должен содержать имя поставщика и URL-адрес поиска. При отсутствии этих элементов установка поставщика поиска в браузере Internet Explorer 8 будет невозможна. В строке запроса каждого URL-адреса поиска должна содержаться фраза (рис 21.10) 06_10.

    21.4.2. Создание файла описания поискового расширения для Интернет-магазина

    Добавим в корень проекта файл Search.xml следующей структуры:

    <?xml version="1.0" encoding="UTF-8"?>
    <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
      <ShortName>Adventure Works</ShortName>
      <Url type="text/html" 
           template="http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query={searchTerms}" />
      <Url type="application/x-suggestions+xml" 
           template="http://localhost:31770/AWCDShop/SearchSuggestion.ashx?query={searchTerms}"/>
    </OpenSearchDescription>

    Как видно из описания, мы не указываем иконку для нашего поиска, а также подсказки в формате JSON. При этом при использовании поиска, пользователь будет перенаправляться на только что разработанную страницу products/ProductsSearch.aspx. Строку, описывающую доступ к подсказкам рассмотрим позднее.

    21.5. Добавление поставщика поиска на страницу сайта

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

    Ниже приведен пример кода, обеспечивающего добавление поставщика поиска при щелчке ссылки пользователем:

    <a href="#"
    onclick="window.external.AddSearchProvider('http://www.example.com/provider.xml')">Add Search Provider Example</a>

    В этом примере вызывается метод AddSearchProvider. Метод AddSearchProvider доступен из объекта external объекта window. При выполнении этого кода на HTML-странице в браузере Internet Explorer 8 открывается диалоговое окно "Добавление поставщика поиска".

    Второй способ информирования пользователя о наличии поискового расширения предусматривает обнаружение поставщика поиска браузером. Это обеспечивается посредством добавления элемента link в объект head веб-страницы. В следующем примере кода выполняется обнаружение поставщика поиска браузером Internet Explorer 8:

    <link title="My Provider" rel="search"
          type="application/opensearchdescription+xml"
          href="http://www.example.com/provider.xml">

    Атрибуту rel необходимо присвоить значение " search ", а атрибуту type – значение " application/opensearchdescription+xml ". Значение атрибута title отображается в раскрывающемся списке поля мгновенного поиска. Атрибут href содержит абсолютный или относительный URL-адрес, определяющий местоположение файла описания OpenSearch.

    При загрузке страницы в браузер Internet Explorer 8 цвет стрелки в раскрывающемся списке поля мгновенного поиска изменяется на оранжевый, что свидетельствует о добавлении в него нового поставщика. Прежде чем добавлять новые поставщики в список, можно ознакомиться с ними. Если пользователь решает установить поставщик поиска, открывается диалоговое окно "Добавление поставщика поиска".

    Расположим на странице master.master в теге head следующий код:

    <link 	rel="search" 	
          type="application/opensearchdescription+xml" 	
          href="http://localhost:31770/AWCDShop/Search.xml" 	
          title="Adventure Works 1" />

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

    21.6. Реализация подсказок

    Теперь перейдем к рассмотрению способов реализации подсказок. В IE поддерживается два способа, стандартный который поддерживают все браузеры, в формате JSON, и расширенный, в формате XML.

    21.6.1. Описание создания JSON подсказок

    Начиная с версии Internet Explorer 8, в поле мгновенного поиска поддерживаются различные варианты поиска. По мере ввода пользователем текста в поле поиска браузер Internet Explorer 8 может предлагать варианты и отправлять в поставщик запросы, содержащие текущую строку поиска. Кроме того, предложенные варианты могут помочь в составлении более эффективных условий поиска. В Internet Explorer 8 поддерживается два формата вариантов поиска: JSON и XML. Формат JSON поддерживает текстовые варианты поиска, которые могут быть дополнены описаниями и URL-адресами. Формат XML поддерживает все виды контента, доступные для вариантов JSON, а также визуальные варианты и названия разделов.

    Варианты поиска JSON возвращаются в виде массива массивов Microsoft JScript. Этот массив содержит четыре значения (табл. 21.2).

    Значения массива Microsoft JScript
    Значение Описание
    Строка запроса (обязательный параметр) Запрашиваемое условие поиска. Например, если в браузере запрашивается вариант для термина " xbox ", в качестве строки запроса необходимо использовать строку " xbox ". Чтобы обеспечить соответствие возвращаемых вариантов запрашиваемому условию поиска, строка запроса возвращается в виде массива.
    Массив вариантов (обязательный параметр) Варианты для заданной строки запроса.
    Массив описаний (необязательный параметр) Дополнительные строки, содержащие дополнительные сведения или контекст для заданного варианта.
    Массив URL-адресов запроса (необязательный параметр) Список URL-адресов, которые следует использовать при выборе пользователем заданного варианта. Эти URL-адреса используются в качестве мгновенного ответа для перенаправления пользователя на заданный URL-адрес вместо страницы результатов поиска.

    В ответе на запрос JSON должны возвращаться строка запроса и массив вариантов. Ниже приведен пример простого ответа на запрос JSON, в котором не указаны описания и URL-адреса.

    ["xbox",
    	["Xbox 360", "Xbox cheats", "Xbox 360 games"]]

    Для создания более эффективных условий поиска вместе с вариантами можно предлагать описание. Чтобы создать ответ, можно добавить URL-адреса запроса. Если предлагается URL-адрес запроса, при выборе пользователем соответствующего варианта браузер Internet Explorer 8 переходит непосредственно по этому URL-адресу, а не на страницу результатов поиска. Ниже приведен пример подробного ответа на запрос JSON.

    ["xbox",
    	["Xbox 360", "Xbox cheats", "Xbox 360 games"], 
    	["The official Xbox website from Microsoft", "Codes and walkthroughs", "Games and accessories"],	
    	["http://www.xbox.com","http://www.example.com/xboxcheatcodes.aspx", "http://www.example.com/games"]]

    В этом ответе на запрос JSON первый вариант поиска состоит из следующих элементов:

  • первый элемент первого массива (Xbox 360);
  • первый элемент второго массива (The official Xbox website from Microsoft);
  • первый элемент третьего массива (http://www.xbox.com).
  • При использовании предыдущего ответа на запрос получаются результаты, показанные на рис.21.6.

    (рис 21.6) Подсказки поискового расширения Microsoft Live

    21.6.2. Использование формата результатов поиска в формате XML

    Приведенный ранее формат ответа на запрос JSON может быть представлен в формате XML, как показано в следующем примере. Этот пример содержит те же самые варианты поиска и дает такие же результаты, что и предшествующий ответ на запрос в формате JSON.

    <?xml version="1.0"?>
    <SearchSuggestion version="2.0" xmlns="http://opensearch.org/searchsuggest2">
      <Query>xbox</Query>
      <Section>
        <Item>
          <Text>Xbox 360</Text>
          <Description>The official Xbox website from Microsoft</Description>
          <Url>http://www.xbox.com</Url>
        </Item>
        <Item>
          <Text>Xbox cheats</Text>
          <Description>Codes and walkthroughs</Description>
          <Url>http://www.example.com/xboxcheatcodes.aspx</Url>
        </Item>
        <Item>
          <Text>Xbox 360 games</Text>
          <Description>Games and accessories</Description>
          <Url>http://www.example.com/games</Url>
        </Item>
      </Section>
    </SearchSuggestion>

    Формат вариантов JSON не поддерживает использование названий разделов в меню вариантов. В Internet Explorer 8 в качестве названия раздела используется слово "Варианты" (Results) в сочетании с именем поставщика поиска. Например, если создан поставщик поиска "Мой поставщик" раздел вариантов будет иметь название "Варианты: Мой поставщик". XML -формат вариантов также используется в тех случаях, когда требуется упорядочить варианты по нескольким разделам. Помимо названий разделов, формат XML поддерживает визуальные варианты.

    Формат XML поддерживает все возможности, доступные для вариантов JSON, а также некоторые дополнительные функции. К этим дополнительным возможностям относятся следующие:

  • настройка названия раздела вариантов;
  • упорядочение вариантов с помощью разделителей разделов;
  • включение визуальных вариантов.
  • Для настройки названий разделов можно добавить атрибут " title " в элемент Section или использовать разделитель. При необходимости разделители могут включать в себя названия. Ниже приведен пример добавления разделителя " My Text Suggestions " и еще одного разделителя без названия.

    <?xml version="1.0"?>
    <SearchSuggestion version="2.0" xmlns="http://opensearch.org/searchsuggest2">
      <Query>xbox</Query>
      <Section>
        <Separator title="My Text Suggestions"/>
        <Item>
          <Text>Xbox 360</Text>
          <Description>The official Xbox website from Microsoft</Description>
          <Url>http://www.xbox.com</Url>
        </Item>
        <Item>
          <Text>Xbox cheats</Text>
          <Description>Codes and walkthroughs</Description>
          <Url>http://www.example.com/xboxcheatcodes.aspx</Url>
        </Item>
        <Item>
          <Text>Xbox 360 games</Text>
          <Description>Games and accessories</Description>
          <Url>http://www.example.com/games</Url>
        </Item>
        <Separator />
        <Item>
          <Text>xbox 360 lowest price</Text>
        </Item>
        <Item>
          <Text>xbox 360 news</Text>
        </Item>
      </Section>
    </SearchSuggestion>

    При выполнении представленного выше кода получается результат, показанный на рис.21.7.

    (рис 21.7) Пример текстовых подсказок и разделителей

    Варианты поиска обычно включают в себя текстовые варианты и сопутствующие термины, которые, возможно, искал пользователь. В браузере Internet Explorer 8 применяется расширенная концепция вариантов поиска, включающая в себя строки запроса, ссылки и изображения. Поставщики поиска могут предоставлять изображения с текстовыми фрагментами или без них в качестве вариантов поиска для заданных пользователем условий. Чтобы добавить визуальный вариант в ответ на запрос, необходимо добавить элемент Image в элемент Item для этого варианта. При этом рекомендуется указать ширину и высоту изображения. Например, чтобы предложить визуальные варианты для термина " Xbox ", необходимо возвращать следующие данные:

    <Separator title="My Visual Suggestions" />
    <Item>
      <Text>Xbox 360 Game Consoles</Text>
      <Description>Game console systems and packages at a great deal.</Description>
      <Image source="http://www.example.com/xboxconsole.jpg" 
             alt="Xbox 360 Consoles" width="75" height="75"/>
      <Url>http://www.example.com/</Url>
    </Item>
    <Item>
      <Text>Xbox 360 Wireless Controller</Text>
      <Image source="http://www.example.com/xboxcontroller.jpg" 
             alt="Xbox 360 Wireless Controller" width="75" height="75"/>
    </Item>
    <Item>
      <Text>Xbox 360 Live Games</Text>
      <Image source="http://www.example.com/live.jpg" 
             alt="Xbox 360 Live Games" width="75" height="75"/>
      <Url>http://www.example.com/games.aspx?q="Xbox 360"</Url>
    </Item>

    Выполнение приведенного выше кода приводит к получению результатов, показанных на рис.21.8.

    (рис 21.8) Пример визуальных подсказок

    В этом примере предлагается URL-адрес с двумя вариантами. В браузере Internet Explorer 8 осуществляется перенаправление пользователя непосредственно на страницу с заданным URL-адресом. Если URL-адрес не указан, в качестве условия поиска используется значение элемента Text (Xbox 360 Wireless Controller). Чтобы предложить визуальные варианты без текста или описания, необходимо указать URL-адрес, по которому будет осуществляться перенаправление пользователя Internet Explorer 8.

    По умолчанию, если визуальный вариант содержит текст, он центрируется по вертикали рядом с изображением. Присваивая атрибуту align значения "top", "middle" или "bottom", можно определить выравнивание текста элементов Text и Description относительно изображения.

    Чтобы задать выравнивание текста, добавьте атрибут align к элементу image. Ниже приведен пример, в котором атрибуту align присваивается значение "top".

    <Image source="http://www.example.com/xboxconsole.jpg" 
           alt="Xbox 360 Consoles" width="75" height="75" align="top"/>

    21.6.3. Добавление в поисковое расширение Интернет-магазина визуальных подсказок

    Разработаем подсказки в формате XML. При этом хранить большой набор XML файлов не имеет смысла, так как угадать все возможные запросы пользователя не представляется возможным, а для созданных файлов будет сложно поддерживать их актуальность. Также нас не устраивает и создание веб-сервиса, так как при использовании поиска используется HTTP GET.

    Для того чтобы реализовать поиск, добавим в корень нашего приложения asp-handler SearchSuggestion.ashx. Соответственно, так как новый класс SearchSuggestion реализует интерфейс IHttpHandler, пользователи и браузер могут обращаться по адресу http://localhost:31770/AWCDShop/SearchSuggestion.ashx для получения результата работу обработчика SearchSuggestion.

    Примечание: при работе через IIS может потребоваться изменение файла web.config и ISAPI-фильтров приложения в IIS.

    В метод ProcessRequest, который и будет обрабатывать полученный запрос, добавим следующий код:

    context.Response.ContentType = "text/plain";
    var q = context.Request["query"];
    if (q==null) q = "";
    DataClassesDataContext dcdc = new DataClassesDataContext
         ("Data Source=localhost;Initial Catalog=AdventureWorks;Integrated Security=True");
    
    var query = from p in dcdc.Products where p.Name.Contains(q) select p;
    query = query.Take(10);
    var sb = new StringBuilder();
    
    MemoryStream ms = new MemoryStream();
    string str = "";
    XmlTextWriter writer = new XmlTextWriter(ms, Encoding.UTF8);
    writer.WriteStartDocument();
    writer.WriteStartElement("SearchSuggestion");
    writer.WriteAttributeString("version","2.0");
    writer.WriteAttributeString("xmlns",null, null, "http://opensearch.org/searchsuggest2");
    writer.WriteStartElement("Query");
    writer.WriteAttributeString("xml", "space",null, "preserve");
    writer.WriteValue(q);
    writer.WriteEndElement();
    writer.WriteStartElement("Section");
    foreach (Product p in query)
    {
      writer.WriteStartElement("Item");
      writer.WriteStartElement("Text");
      writer.WriteAttributeString("xml", "space", null, "preserve");
      writer.WriteValue(p.Name);
      writer.WriteEndElement();
      
      writer.WriteStartElement("Url");
      writer.WriteAttributeString("xml", "space", null, "preserve");
      writer.WriteValue("http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query="+p.Name);
      writer.WriteEndElement();
      
      writer.WriteStartElement("Description");
      writer.WriteAttributeString("xml", "space", null, "preserve");
      writer.WriteValue((p.ProductModel != null 
                      p.ProductModel.ProductModelProductDescriptionCultures.Count > 0)
                         ? p.ProductModel.ProductModelProductDescriptionCultures[0].ProductDescription.
                               Description
                         : "");
      writer.WriteEndElement();
    
      writer.WriteStartElement("Image");
      writer.WriteAttributeString("xml", "space", null, "preserve");
      writer.WriteAttributeString("width", "80");
      writer.WriteAttributeString("height", "49");
      writer.WriteAttributeString("align", "middle");
      writer.WriteAttributeString("source", 
                "http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/" +
                p.ProductProductPhotos[0].ProductPhoto.ThumbnailPhotoFileName);
      writer.WriteEndElement();
      
      writer.WriteEndElement();
    }
    writer.WriteEndElement();
    writer.WriteEndElement();
    writer.WriteEndDocument();
    writer.Flush();
    ms.Position = 0;
    var sr = new StreamReader(ms);
    
    context.Response.Write(sr.ReadToEnd());

    Разберем этот код. Вначале мы определяем Mime-type ответа обработчика как "text/plain". Затем извлекаем переданный через запрос параметр query, и при помощи LINQ выбираем первые 10 продуктов, которые содержат в своем имени переданную строку. Выбирать более 10 не имеет смысла еще и потому, что IE отображает не более 10 подсказок. Далее при помощи класса XMLTextWriter формируем соответствующий XML файл.

    Примечание: здесь, как и раньше для картинок и ссылок используются адреса, начинающиеся с http://localhost:31770. В случае использования другого порта для dev-server 'а или IIS этот адрес необходимо заменить. В некоторых случаях можно обойтись и использование относительных ссылок, а не абсолютных.

    В конце записываем содержимое XML -документа, хранящиеся в потоке ms в Response.

    Вот вариант ответа обработчика на запрос " bike ":

    <?xml version="1.0" encoding="utf-8" ?>
    <SearchSuggestion version="2.0" xmlns="http://opensearch.org/searchsuggest2">
      <Query xml:space="preserve">bike</Query>
      <Section>
        <Item>
          <Text xml:space="preserve">All-Purpose Bike Stand</Text>
          <Url xml:space="preserve">http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=All-Purpose Bike Stand</Url>
          <Description xml:space="preserve">
             Perfect all-purpose bike stand for working on your bike at home. Quick-adjusting clamps and steel construction.
          </Description>
          <Image xml:space="preserve" width="80" height="49" align="middle" 
                 source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
        </Item>
        <Item>
          <Text xml:space="preserve">Bike Wash – Dissolver</Text>
          <Url xml:space="preserve">
             http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=Bike Wash – Dissolver
          </Url>
          <Description xml:space="preserve">
             Washes off the toughest road grime; dissolves grease, environmentally safe. 1-liter bottle.
          </Description>
          <Image xml:space="preserve" width="80" height="49" align="middle" 
                 source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
        </Item>
        <Item>
          <Text xml:space="preserve">Hitch Rack – 4-Bike</Text>
          <Url xml:space="preserve">
             http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=Hitch Rack – 4-Bike
          </Url>
          <Description xml:space="preserve">
             Carries 4 bikes securely; steel construction, fits 2" receiver hitch.
          </Description>
          <Image xml:space="preserve" width="80" height="49" align="middle" 
                 source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
        </Item>
        <Item>
          <Text xml:space="preserve">Mountain Bike Socks, L</Text>
          <Url xml:space="preserve">
             http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=Mountain Bike Socks, L
          </Url>
          <Description xml:space="preserve">
             Combination of natural and synthetic fibers stays dry and provides just the right cushioning.
          </Description>
          <Image xml:space="preserve" width="80" height="49" align="middle" 
                 source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
        </Item>
        <Item>
          <Text xml:space="preserve">Mountain Bike Socks, M</Text>
          <Url xml:space="preserve">
             http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=Mountain Bike Socks, M
          </Url>
          <Description xml:space="preserve">
             Combination of natural and synthetic fibers stays dry and provides just the right cushioning.
          </Description>
          <Image xml:space="preserve" width="80" height="49" align="middle" 
                 source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
        </Item>
      </Section>
    </SearchSuggestion>
    Примечание: стоит обратить внимание, что у большинства сформированных тегов указаны пространства имен. Если их не указать, то подсказки в IE8 отображаться не будут.

    Теперь запустим браузер и проверим результат работы рис.21.9.

    (рис 21.9) Пример работы поискового расширения интернет-магазина Adventure Works

    21.7. Ключевые термины

    Интернет-поиск, OpenSearch, Search Suggestions, Поисковое расширение, Файлы описания OpenSearch, JSON, XML.

    21.8. Краткие итоги

    Данное практическое занятие рассматривает следующие темы:

  • Структура и формат файла описания OpenSearch ;
  • Создание файла описания поискового расширения для Интернет-магазина;
  • Добавление поставщика поиска на страницу сайта;
  • Реализация JSON подсказок;
  • Использование формата результатов поиска в формате XML ;
  • Добавление в поисковое расширение Интернет-магазина визуальных подсказок.
  • Страницы:

    Цель практического занятия: В Internet Explorer 7 появилась возможность выполнять быстрый поиск через специальную панель. В Internet Explorer 8 возможности такого быстрого поиска были расширены, за счет добавления визуальных возможностей и изменения шаблона отображения. Целью данного семинара является рассмотрение технологии разработки собственного поискового расширение для Интернет-магазина, опираясь на стандарт OpenSearch.

    Файлы к практическому занятию Вы можете скачать здесь.

    21.1. Архитектура

    OpenSearch – набор технологий, позволяющих веб-сайтам и поисковым системам публиковать результаты поиска в форматах, удобных для распространения и сбора.

    OpenSearch был разработан A9, дочерней компанией Amazon.com. Первая версия, OpenSearch 1.0, была представлена на конференции, посвященной Web 2.0 в марте 2005 года. Черновые версии OpenSearch 1.1 были опубликованы в сентябре и декабре 2005 года. Спецификация OpenSearch лицензирована компанией A9 по Creative Commons Attribution-ShareAlike 2.5 License.

    В OpenSearch входят:

  • XML -файлы с описанием поисковой системы;
  • стандартизованный синтаксис запросов, описывающий, где и как получать результаты поиска;
  • RSS (в OpenSearch 1.0) или более общий OpenSearch -ответ (в OpenSearch 1.1) – форматы, предоставляющие поисковые результаты;
  • OpenSearch -агрегаторы – сайты, позволяющие отображать OpenSearch -результаты;
  • элементы на веб-странице для автоматического обнаружения пользовательским клиентом возможности использования OpenSearch на данном сайте.
  • Версия 1.0 спецификации позволяла предоставлять результаты поисковых запросов только в формате RSS, в то время как версия 1.1 позволяет использовать RSS и Atom – единственные форматы, формально поддерживаемые OpenSearch -агрегаторами, но и другие типы вполне допустимы, например, HTML.

    21.2. Поисковые системы и ПО, поддерживающие OpenSearch

    К поисковым системам и программному обеспечению, поддерживающему OpenSearch относятся:

  • Википедия предлагает статьи, соответствующие введенной строке;
  • Mozilla Firefox версии 2 и выше позволяет интегрировать поисковые системы, поддерживающие OpenSearch, со своей панелью поиска;
  • Internet Explorer версии 7 и выше так же позволяет добавлять OpenSearch -системы.
  • Функция Search Suggestions (поисковые подсказки) предлагает пользователю по мере ввода им информации подходящие варианты, соответствующие вводимому запросу. Это очень удобно, если неизвестно, как правильно пишется чье-то имя, или как полностью называется организация. Многие сайты, такие как yandex.ru или google.com предоставляют данную функцию, использую формат JSON. При этом IE8 также поддерживает JSON suggestions.

    В IE8 возможности функции расширены за счет добавления графических подсказок. На рис.21.1 можно видеть текстовые подсказки графические подсказки с Amazon.com.

    (рис 21.1) Графические подсказки поискового расширения сайта Amazon.com

    Некоторые из подсказок включают дополнительный текст, выделенный серым курсивом. Он лишь описывает результаты запроса. Это позволяет принять осмысленное решение о том, какой из результатов наиболее полно соответствует запросу. Более того поисковые провайдеры могут добавлять дополнительные разделители к подсказкам. Так, к примеру, и eBay и The New York Times реализовали разделители, отделяющие товары от различного рода публикаций (рис.21.2).

    (рис 21.2) Пример разделителей поискового расширения сайта eBay

    21.2.1. Пример поиска на Википедии

    Как пример, рассмотрим поисковое расширение, поставляемое сайтом Wikipedia.org. При переходе на любую страницу англоязычной Википедии, кнопка выбора поиска меняет свой цвет, показывая, что данный сайт предоставляет свое расширение (рис.21.3).

    (рис 21.3) Уведомление пользователя о том, что текущий сайт содержит поисковый провайдер

    После установки расширения, у пользователя появляется возможность мгновенно искать информацию по Википедии, находясь на любом другом сайте. Так, при вводе запроса Moscow можно наблюдать результат, показанный на рис.21.4.

    (рис 21.4) Пример поискового расширения сайта Wikipedia.org

    Видно, что для каждой найденной страницы отображается ее название, краткое описание и в тех случаях, когда это возможно, картинка. Аналогичное поисковое расширение мы разработаем и для нашего Интернет-магазина.

    21.3. Создание поисковой страницы

    Прежде чем приступать к разработке поискового расширения для IE необходимо создать страницу (или набор страниц и сервисов) для поиска в нашем Интернет-магазине. Для этого добавим в папку Products еще одну страницу – ProductsSearch.aspx и скопируем ASP-код для левого PlaceHolder 'а из products/default.aspx. Удалим обработчик выбора строки, так как сейчас нас интересует только сам поиск, а не просмотр результатов. В бэк-коде реализуем метод Page_Load следующим образом:

    GridViewProducts.DataKeyNames = new string[]
      {
        "ProductID"
      };
    
    ProductsLinqDataSource.Where = "";
    ProductsLinqDataSource.WhereParameters.Clear();
    if (!string.IsNullOrEmpty(Request.QueryString["query"]))
    {
      ProductsLinqDataSource.Where = "Name.Contains(@query)";
      ProductsLinqDataSource.WhereParameters.Add("query", DbType.String, 
                                            Request.QueryString["query"]);
    }

    Этот код похож на тот, что мы писали при разработке страницы products/default.aspx, однако здесь, вместо ограничения категории или подкатегории продуктов мы задаем фильтр на название продукта. При выполнении запроса LINQ преобразует код "Name.Contains(@query)" примерно в следующий SQL запрос:

    Where Name Like '%@query%'
    Примечание: здесь метод Contains – это метод класса string, проверяющий на вхождение переданной в параметре строки в строку Name. В общем случае здесь же необходимо проверить query на null, иначе null будет трактоваться как object и метод string.Contains(object o) не будет найден. Один из самых простых вариантов – добавить в конце строчку:
    ProductsLinqDataSource.WhereParameters[0].ConvertEmptyStringToNull = false;
    Примечание: в идеале на страницу стоит добавить текстовое поле и кнопку, при нажатии на которую и будет происходить поиск товара, но в данном случае мы разрабатываем страницу, которая будет открываться при поиске через сам браузер.

    Параметр поиска будет передаваться через запрос, и называться query. Проверим разработанную страницу, поискав все продукты, содержащие в названии ' bike '.

    Для этого обратимся по адресу http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=bike (рис.21.5).

    (рис 21.5) Страница поиска интернет-магазина Adventure Works

    21.4. Создание файла описания поискового расширения

    Теперь необходимо разработать само поисковое расширение. Как уже отмечалось, это небольшой файл в формате xml.

    21.4.1. Структура и формат файла описания OpenSearch

    Файлы описания OpenSearch – это небольшие XML -файлы, содержащие описание поставщика поиска для браузера Internet Explorer 8. В табл. 21.1 описываются значения, используемые в файле описания OpenSearch.

    Файл описания OpenSearch
    Значение Описание
    ShortName (обязательный параметр) Имя поставщика поиска, отображаемое при выборе поставщика в поле мгновенного поиска.
    URL (обязательный параметр) URL-адрес для основных поисковых запросов поставщика. Необходимо указывать абсолютный URL-адрес.
    Image (необязательный параметр) Указатель на файл значка, связанного с поставщиком поиска на веб-сайте. Этот значок отображается рядом с именем поставщика в поле мгновенного поиска. Если не указан допустимый файл значка ярлыка, используется общий значок.
    Suggestions URL ( JSON ) (необязательный параметр) URL-адрес, по которому могут быть извлечены варианты поиска с использованием нотации объектов JavaScript ( JSON ).
    Suggestions URL ( XML ) (необязательный параметр) URL-адрес, по которому могут быть извлечены варианты поиска в формате XML.
    PreviewUrl (необязательный параметр) URL-адрес для отображения результатов в окне предварительного просмотра ускорителя.

    Ниже приведен образец файла описания OpenSearch, в котором определяется тип предоставляемых поисковых служб:

    <?xml version="1.0" encoding="UTF-8"?>
    <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" 
                           xmlns:ie="http://schemas.microsoft.com/Search/2008/">
      <ShortName>My Custom Search</ShortName>
      <Image height="16" width="16" type="image/icon">
         http://example.com/example.ico
      </Image>
      <Url type="text/html" 
           template="http://example.com/search.aspx?q={searchTerms}amp;source=IE"/>
      <Url type="application/x-suggestions+json" 
           template="http://suggestions.example.com/search.aspx?q={searchTerms}"/>
      <Url type="application/x-suggestions+xml" 
           template="http://suggestions.example.com/search.aspx?q={searchTerms}"/>
      <ie:PreviewUrl type="text/html" 
           template="http://suggestions.example.com/search.aspx?q={searchTerms}"/>
    </OpenSearchDescription>

    Каждый файл описания OpenSearch должен содержать имя поставщика и URL-адрес поиска. При отсутствии этих элементов установка поставщика поиска в браузере Internet Explorer 8 будет невозможна. В строке запроса каждого URL-адреса поиска должна содержаться фраза (рис 21.10) 06_10.

    21.4.2. Создание файла описания поискового расширения для Интернет-магазина

    Добавим в корень проекта файл Search.xml следующей структуры:

    <?xml version="1.0" encoding="UTF-8"?>
    <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
      <ShortName>Adventure Works</ShortName>
      <Url type="text/html" 
           template="http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query={searchTerms}" />
      <Url type="application/x-suggestions+xml" 
           template="http://localhost:31770/AWCDShop/SearchSuggestion.ashx?query={searchTerms}"/>
    </OpenSearchDescription>

    Как видно из описания, мы не указываем иконку для нашего поиска, а также подсказки в формате JSON. При этом при использовании поиска, пользователь будет перенаправляться на только что разработанную страницу products/ProductsSearch.aspx. Строку, описывающую доступ к подсказкам рассмотрим позднее.

    21.5. Добавление поставщика поиска на страницу сайта

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

    Ниже приведен пример кода, обеспечивающего добавление поставщика поиска при щелчке ссылки пользователем:

    <a href="#"
    onclick="window.external.AddSearchProvider('http://www.example.com/provider.xml')">Add Search Provider Example</a>

    В этом примере вызывается метод AddSearchProvider. Метод AddSearchProvider доступен из объекта external объекта window. При выполнении этого кода на HTML-странице в браузере Internet Explorer 8 открывается диалоговое окно "Добавление поставщика поиска".

    Второй способ информирования пользователя о наличии поискового расширения предусматривает обнаружение поставщика поиска браузером. Это обеспечивается посредством добавления элемента link в объект head веб-страницы. В следующем примере кода выполняется обнаружение поставщика поиска браузером Internet Explorer 8:

    <link title="My Provider" rel="search"
          type="application/opensearchdescription+xml"
          href="http://www.example.com/provider.xml">

    Атрибуту rel необходимо присвоить значение " search ", а атрибуту type – значение " application/opensearchdescription+xml ". Значение атрибута title отображается в раскрывающемся списке поля мгновенного поиска. Атрибут href содержит абсолютный или относительный URL-адрес, определяющий местоположение файла описания OpenSearch.

    При загрузке страницы в браузер Internet Explorer 8 цвет стрелки в раскрывающемся списке поля мгновенного поиска изменяется на оранжевый, что свидетельствует о добавлении в него нового поставщика. Прежде чем добавлять новые поставщики в список, можно ознакомиться с ними. Если пользователь решает установить поставщик поиска, открывается диалоговое окно "Добавление поставщика поиска".

    Расположим на странице master.master в теге head следующий код:

    <link 	rel="search" 	
          type="application/opensearchdescription+xml" 	
          href="http://localhost:31770/AWCDShop/Search.xml" 	
          title="Adventure Works 1" />

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

    21.6. Реализация подсказок

    Теперь перейдем к рассмотрению способов реализации подсказок. В IE поддерживается два способа, стандартный который поддерживают все браузеры, в формате JSON, и расширенный, в формате XML.

    21.6.1. Описание создания JSON подсказок

    Начиная с версии Internet Explorer 8, в поле мгновенного поиска поддерживаются различные варианты поиска. По мере ввода пользователем текста в поле поиска браузер Internet Explorer 8 может предлагать варианты и отправлять в поставщик запросы, содержащие текущую строку поиска. Кроме того, предложенные варианты могут помочь в составлении более эффективных условий поиска. В Internet Explorer 8 поддерживается два формата вариантов поиска: JSON и XML. Формат JSON поддерживает текстовые варианты поиска, которые могут быть дополнены описаниями и URL-адресами. Формат XML поддерживает все виды контента, доступные для вариантов JSON, а также визуальные варианты и названия разделов.

    Варианты поиска JSON возвращаются в виде массива массивов Microsoft JScript. Этот массив содержит четыре значения (табл. 21.2).

    Значения массива Microsoft JScript
    Значение Описание
    Строка запроса (обязательный параметр) Запрашиваемое условие поиска. Например, если в браузере запрашивается вариант для термина " xbox ", в качестве строки запроса необходимо использовать строку " xbox ". Чтобы обеспечить соответствие возвращаемых вариантов запрашиваемому условию поиска, строка запроса возвращается в виде массива.
    Массив вариантов (обязательный параметр) Варианты для заданной строки запроса.
    Массив описаний (необязательный параметр) Дополнительные строки, содержащие дополнительные сведения или контекст для заданного варианта.
    Массив URL-адресов запроса (необязательный параметр) Список URL-адресов, которые следует использовать при выборе пользователем заданного варианта. Эти URL-адреса используются в качестве мгновенного ответа для перенаправления пользователя на заданный URL-адрес вместо страницы результатов поиска.

    В ответе на запрос JSON должны возвращаться строка запроса и массив вариантов. Ниже приведен пример простого ответа на запрос JSON, в котором не указаны описания и URL-адреса.

    ["xbox",
    	["Xbox 360", "Xbox cheats", "Xbox 360 games"]]

    Для создания более эффективных условий поиска вместе с вариантами можно предлагать описание. Чтобы создать ответ, можно добавить URL-адреса запроса. Если предлагается URL-адрес запроса, при выборе пользователем соответствующего варианта браузер Internet Explorer 8 переходит непосредственно по этому URL-адресу, а не на страницу результатов поиска. Ниже приведен пример подробного ответа на запрос JSON.

    ["xbox",
    	["Xbox 360", "Xbox cheats", "Xbox 360 games"], 
    	["The official Xbox website from Microsoft", "Codes and walkthroughs", "Games and accessories"],	
    	["http://www.xbox.com","http://www.example.com/xboxcheatcodes.aspx", "http://www.example.com/games"]]

    В этом ответе на запрос JSON первый вариант поиска состоит из следующих элементов:

  • первый элемент первого массива (Xbox 360);
  • первый элемент второго массива (The official Xbox website from Microsoft);
  • первый элемент третьего массива (http://www.xbox.com).
  • При использовании предыдущего ответа на запрос получаются результаты, показанные на рис.21.6.

    (рис 21.6) Подсказки поискового расширения Microsoft Live

    21.6.2. Использование формата результатов поиска в формате XML

    Приведенный ранее формат ответа на запрос JSON может быть представлен в формате XML, как показано в следующем примере. Этот пример содержит те же самые варианты поиска и дает такие же результаты, что и предшествующий ответ на запрос в формате JSON.

    <?xml version="1.0"?>
    <SearchSuggestion version="2.0" xmlns="http://opensearch.org/searchsuggest2">
      <Query>xbox</Query>
      <Section>
        <Item>
          <Text>Xbox 360</Text>
          <Description>The official Xbox website from Microsoft</Description>
          <Url>http://www.xbox.com</Url>
        </Item>
        <Item>
          <Text>Xbox cheats</Text>
          <Description>Codes and walkthroughs</Description>
          <Url>http://www.example.com/xboxcheatcodes.aspx</Url>
        </Item>
        <Item>
          <Text>Xbox 360 games</Text>
          <Description>Games and accessories</Description>
          <Url>http://www.example.com/games</Url>
        </Item>
      </Section>
    </SearchSuggestion>

    Формат вариантов JSON не поддерживает использование названий разделов в меню вариантов. В Internet Explorer 8 в качестве названия раздела используется слово "Варианты" (Results) в сочетании с именем поставщика поиска. Например, если создан поставщик поиска "Мой поставщик" раздел вариантов будет иметь название "Варианты: Мой поставщик". XML -формат вариантов также используется в тех случаях, когда требуется упорядочить варианты по нескольким разделам. Помимо названий разделов, формат XML поддерживает визуальные варианты.

    Формат XML поддерживает все возможности, доступные для вариантов JSON, а также некоторые дополнительные функции. К этим дополнительным возможностям относятся следующие:

  • настройка названия раздела вариантов;
  • упорядочение вариантов с помощью разделителей разделов;
  • включение визуальных вариантов.
  • Для настройки названий разделов можно добавить атрибут " title " в элемент Section или использовать разделитель. При необходимости разделители могут включать в себя названия. Ниже приведен пример добавления разделителя " My Text Suggestions " и еще одного разделителя без названия.

    <?xml version="1.0"?>
    <SearchSuggestion version="2.0" xmlns="http://opensearch.org/searchsuggest2">
      <Query>xbox</Query>
      <Section>
        <Separator title="My Text Suggestions"/>
        <Item>
          <Text>Xbox 360</Text>
          <Description>The official Xbox website from Microsoft</Description>
          <Url>http://www.xbox.com</Url>
        </Item>
        <Item>
          <Text>Xbox cheats</Text>
          <Description>Codes and walkthroughs</Description>
          <Url>http://www.example.com/xboxcheatcodes.aspx</Url>
        </Item>
        <Item>
          <Text>Xbox 360 games</Text>
          <Description>Games and accessories</Description>
          <Url>http://www.example.com/games</Url>
        </Item>
        <Separator />
        <Item>
          <Text>xbox 360 lowest price</Text>
        </Item>
        <Item>
          <Text>xbox 360 news</Text>
        </Item>
      </Section>
    </SearchSuggestion>

    При выполнении представленного выше кода получается результат, показанный на рис.21.7.

    (рис 21.7) Пример текстовых подсказок и разделителей

    Варианты поиска обычно включают в себя текстовые варианты и сопутствующие термины, которые, возможно, искал пользователь. В браузере Internet Explorer 8 применяется расширенная концепция вариантов поиска, включающая в себя строки запроса, ссылки и изображения. Поставщики поиска могут предоставлять изображения с текстовыми фрагментами или без них в качестве вариантов поиска для заданных пользователем условий. Чтобы добавить визуальный вариант в ответ на запрос, необходимо добавить элемент Image в элемент Item для этого варианта. При этом рекомендуется указать ширину и высоту изображения. Например, чтобы предложить визуальные варианты для термина " Xbox ", необходимо возвращать следующие данные:

    <Separator title="My Visual Suggestions" />
    <Item>
      <Text>Xbox 360 Game Consoles</Text>
      <Description>Game console systems and packages at a great deal.</Description>
      <Image source="http://www.example.com/xboxconsole.jpg" 
             alt="Xbox 360 Consoles" width="75" height="75"/>
      <Url>http://www.example.com/</Url>
    </Item>
    <Item>
      <Text>Xbox 360 Wireless Controller</Text>
      <Image source="http://www.example.com/xboxcontroller.jpg" 
             alt="Xbox 360 Wireless Controller" width="75" height="75"/>
    </Item>
    <Item>
      <Text>Xbox 360 Live Games</Text>
      <Image source="http://www.example.com/live.jpg" 
             alt="Xbox 360 Live Games" width="75" height="75"/>
      <Url>http://www.example.com/games.aspx?q="Xbox 360"</Url>
    </Item>

    Выполнение приведенного выше кода приводит к получению результатов, показанных на рис.21.8.

    (рис 21.8) Пример визуальных подсказок

    В этом примере предлагается URL-адрес с двумя вариантами. В браузере Internet Explorer 8 осуществляется перенаправление пользователя непосредственно на страницу с заданным URL-адресом. Если URL-адрес не указан, в качестве условия поиска используется значение элемента Text (Xbox 360 Wireless Controller). Чтобы предложить визуальные варианты без текста или описания, необходимо указать URL-адрес, по которому будет осуществляться перенаправление пользователя Internet Explorer 8.

    По умолчанию, если визуальный вариант содержит текст, он центрируется по вертикали рядом с изображением. Присваивая атрибуту align значения "top", "middle" или "bottom", можно определить выравнивание текста элементов Text и Description относительно изображения.

    Чтобы задать выравнивание текста, добавьте атрибут align к элементу image. Ниже приведен пример, в котором атрибуту align присваивается значение "top".

    <Image source="http://www.example.com/xboxconsole.jpg" 
           alt="Xbox 360 Consoles" width="75" height="75" align="top"/>

    21.6.3. Добавление в поисковое расширение Интернет-магазина визуальных подсказок

    Разработаем подсказки в формате XML. При этом хранить большой набор XML файлов не имеет смысла, так как угадать все возможные запросы пользователя не представляется возможным, а для созданных файлов будет сложно поддерживать их актуальность. Также нас не устраивает и создание веб-сервиса, так как при использовании поиска используется HTTP GET.

    Для того чтобы реализовать поиск, добавим в корень нашего приложения asp-handler SearchSuggestion.ashx. Соответственно, так как новый класс SearchSuggestion реализует интерфейс IHttpHandler, пользователи и браузер могут обращаться по адресу http://localhost:31770/AWCDShop/SearchSuggestion.ashx для получения результата работу обработчика SearchSuggestion.

    Примечание: при работе через IIS может потребоваться изменение файла web.config и ISAPI-фильтров приложения в IIS.

    В метод ProcessRequest, который и будет обрабатывать полученный запрос, добавим следующий код:

    context.Response.ContentType = "text/plain";
    var q = context.Request["query"];
    if (q==null) q = "";
    DataClassesDataContext dcdc = new DataClassesDataContext
         ("Data Source=localhost;Initial Catalog=AdventureWorks;Integrated Security=True");
    
    var query = from p in dcdc.Products where p.Name.Contains(q) select p;
    query = query.Take(10);
    var sb = new StringBuilder();
    
    MemoryStream ms = new MemoryStream();
    string str = "";
    XmlTextWriter writer = new XmlTextWriter(ms, Encoding.UTF8);
    writer.WriteStartDocument();
    writer.WriteStartElement("SearchSuggestion");
    writer.WriteAttributeString("version","2.0");
    writer.WriteAttributeString("xmlns",null, null, "http://opensearch.org/searchsuggest2");
    writer.WriteStartElement("Query");
    writer.WriteAttributeString("xml", "space",null, "preserve");
    writer.WriteValue(q);
    writer.WriteEndElement();
    writer.WriteStartElement("Section");
    foreach (Product p in query)
    {
      writer.WriteStartElement("Item");
      writer.WriteStartElement("Text");
      writer.WriteAttributeString("xml", "space", null, "preserve");
      writer.WriteValue(p.Name);
      writer.WriteEndElement();
      
      writer.WriteStartElement("Url");
      writer.WriteAttributeString("xml", "space", null, "preserve");
      writer.WriteValue("http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query="+p.Name);
      writer.WriteEndElement();
      
      writer.WriteStartElement("Description");
      writer.WriteAttributeString("xml", "space", null, "preserve");
      writer.WriteValue((p.ProductModel != null 
                      p.ProductModel.ProductModelProductDescriptionCultures.Count > 0)
                         ? p.ProductModel.ProductModelProductDescriptionCultures[0].ProductDescription.
                               Description
                         : "");
      writer.WriteEndElement();
    
      writer.WriteStartElement("Image");
      writer.WriteAttributeString("xml", "space", null, "preserve");
      writer.WriteAttributeString("width", "80");
      writer.WriteAttributeString("height", "49");
      writer.WriteAttributeString("align", "middle");
      writer.WriteAttributeString("source", 
                "http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/" +
                p.ProductProductPhotos[0].ProductPhoto.ThumbnailPhotoFileName);
      writer.WriteEndElement();
      
      writer.WriteEndElement();
    }
    writer.WriteEndElement();
    writer.WriteEndElement();
    writer.WriteEndDocument();
    writer.Flush();
    ms.Position = 0;
    var sr = new StreamReader(ms);
    
    context.Response.Write(sr.ReadToEnd());

    Разберем этот код. Вначале мы определяем Mime-type ответа обработчика как "text/plain". Затем извлекаем переданный через запрос параметр query, и при помощи LINQ выбираем первые 10 продуктов, которые содержат в своем имени переданную строку. Выбирать более 10 не имеет смысла еще и потому, что IE отображает не более 10 подсказок. Далее при помощи класса XMLTextWriter формируем соответствующий XML файл.

    Примечание: здесь, как и раньше для картинок и ссылок используются адреса, начинающиеся с http://localhost:31770. В случае использования другого порта для dev-server 'а или IIS этот адрес необходимо заменить. В некоторых случаях можно обойтись и использование относительных ссылок, а не абсолютных.

    В конце записываем содержимое XML -документа, хранящиеся в потоке ms в Response.

    Вот вариант ответа обработчика на запрос " bike ":

    <?xml version="1.0" encoding="utf-8" ?>
    <SearchSuggestion version="2.0" xmlns="http://opensearch.org/searchsuggest2">
      <Query xml:space="preserve">bike</Query>
      <Section>
        <Item>
          <Text xml:space="preserve">All-Purpose Bike Stand</Text>
          <Url xml:space="preserve">http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=All-Purpose Bike Stand</Url>
          <Description xml:space="preserve">
             Perfect all-purpose bike stand for working on your bike at home. Quick-adjusting clamps and steel construction.
          </Description>
          <Image xml:space="preserve" width="80" height="49" align="middle" 
                 source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
        </Item>
        <Item>
          <Text xml:space="preserve">Bike Wash – Dissolver</Text>
          <Url xml:space="preserve">
             http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=Bike Wash – Dissolver
          </Url>
          <Description xml:space="preserve">
             Washes off the toughest road grime; dissolves grease, environmentally safe. 1-liter bottle.
          </Description>
          <Image xml:space="preserve" width="80" height="49" align="middle" 
                 source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
        </Item>
        <Item>
          <Text xml:space="preserve">Hitch Rack – 4-Bike</Text>
          <Url xml:space="preserve">
             http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=Hitch Rack – 4-Bike
          </Url>
          <Description xml:space="preserve">
             Carries 4 bikes securely; steel construction, fits 2" receiver hitch.
          </Description>
          <Image xml:space="preserve" width="80" height="49" align="middle" 
                 source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
        </Item>
        <Item>
          <Text xml:space="preserve">Mountain Bike Socks, L</Text>
          <Url xml:space="preserve">
             http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=Mountain Bike Socks, L
          </Url>
          <Description xml:space="preserve">
             Combination of natural and synthetic fibers stays dry and provides just the right cushioning.
          </Description>
          <Image xml:space="preserve" width="80" height="49" align="middle" 
                 source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
        </Item>
        <Item>
          <Text xml:space="preserve">Mountain Bike Socks, M</Text>
          <Url xml:space="preserve">
             http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=Mountain Bike Socks, M
          </Url>
          <Description xml:space="preserve">
             Combination of natural and synthetic fibers stays dry and provides just the right cushioning.
          </Description>
          <Image xml:space="preserve" width="80" height="49" align="middle" 
                 source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
        </Item>
      </Section>
    </SearchSuggestion>
    Примечание: стоит обратить внимание, что у большинства сформированных тегов указаны пространства имен. Если их не указать, то подсказки в IE8 отображаться не будут.

    Теперь запустим браузер и проверим результат работы рис.21.9.

    (рис 21.9) Пример работы поискового расширения интернет-магазина Adventure Works

    21.7. Ключевые термины

    Интернет-поиск, OpenSearch, Search Suggestions, Поисковое расширение, Файлы описания OpenSearch, JSON, XML.

    21.8. Краткие итоги

    Данное практическое занятие рассматривает следующие темы:

  • Структура и формат файла описания OpenSearch ;
  • Создание файла описания поискового расширения для Интернет-магазина;
  • Добавление поставщика поиска на страницу сайта;
  • Реализация JSON подсказок;
  • Использование формата результатов поиска в формате XML ;
  • Добавление в поисковое расширение Интернет-магазина визуальных подсказок.
  • Вернуться к учебному плану