ASP.NET MVC: История одного проекта Поиск (часть 10)
Содержание
ASP.NET MVC: История одного проекта "Готовимся к старту" (часть 1)
ASP.NET MVC: История одного проекта "Всё ради данных" (часть 2)
ASP.NET MVC: История одного проекта "Шаблоны и внешний вид" (часть 3)
ASP.NET MVC: История одного проекта "Еще немного классов" (часть 4)
ASP.NET MVC: История одного проекта "UI - всё для пользователя" (часть 5)
ASP.NET MVC: История одного проекта "UI - Добавление экспоната" (часть 6)
ASP.NET MVC: История одного проекта "UI - Редактирование экспоната" (часть 7)
ASP.NET MVC: История одного проекта "Обработка ошибок" (часть 8)
ASP.NET MVC: История одного проекта "Фильтрация" (часть 9)
ASP.NET MVC: История одного проекта "Поиск" (часть 10)
ASP.NET MVC: История одного проекта "Облако тегов" (часть 11)
ASP.NET MVC: История одного проекта "Главная страница" (часть 12)
Задача
Мне требуется создать универсальный поиск, с возможностью расширения списка типов сущностей, по которым можно осуществлять поиск. Поиск должен осуществляться через autocomplete-поле на всех страницах сайта. Для этого надо все типы сущностей: экспонат, лента, метка "засунуть" в один список, который через AJAX будет возвращать JSON-объекты в выпадающий список.
Поле ввода запроса
Куда положить поле ввода, это риторический вопрос. Конечно же в шаблон (_LayoutExtended), чтобы поле было доступно с любой страницы сайта (отключение поиска на избранных страницах, например, ввод логина и пароля, пока не будем обсуждать, но это в планах). Я создам UserControl, который будет отображать само поле ввода и содержать скрипты (у нас же ajax), которые будут обслуживать это поле:
Вот код разметки:
@Html.TextBox("searcher", null, new { data_autocomplete = @Url.Content("/site/search/") }) @Html.ScriptBlock( @<script type="text/javascript" src="@Url.Content("/scripts/search.mvc.helpers.js")"> </script>) @Html.ScriptBlock( @<script type="text/javascript" src="@Url.Content("/scripts/jquery.blockUI.js")"> </script>)
Как видно из разметки есть поле ввода и два скрипта: один - работает с поле ввода, второй - "прячет" от пользователя контент сайта, на время, пока происходит перенаправление на выбранный из списка элемент. Показывать второй скрипт я не буду, вы можете найти подобного рода скриптов на jQuery огромное количество в интернете или, в конце-концов, написать свой скрипт с таким функционалом. А вот первый я создам в папке Scripts, он пока пустой займемся им позже.
Откуда контент-то? Дык, JsonResult есть!
Поместить метод поиска Search разумнее всего в основной для сайта контролер, чтобы доступность метода не перекрывалась необходимостью авторизации и аутентификации. Значит в моем случае, в контролле SiteController:
public JsonResult Search() { return Json("", JsonRequestBehavior.AllowGet); }
Пока он тоже "пустой". А прежде чем начать писать что-то, я бы хотел объяснить, что я собираюсь сделать. Разложить, так сказать, по полочкам вариант реализации.
SearchItem базовый класс для поиска
Чтобы получить возможность наполнить выпадающий список autocomplete, надо чтобы сущности были одного типа (я не буду сейчас говорить про Tuple), иначе придется выдавать из метода Search (JsonResult) несколько списков, а потом еще и обрабатывать их по разному, в зависимости от полей и свойств, которые есть в этих классах. Я упрощу себе задачу, создам один абстрактный базовый класс SearchItem. От этого класса унаследую все классы, которые и будут иметь возможность отображаться в списке при поиске:
/// <summary>
/// Базовый класс для всех сущностей,
/// от которого должна быть унаследована сущность
/// чтобы иметь возможность поиска по ней
/// </summary>
public abstract class SearchItem {
/// <summary>
/// Идентификатор
/// </summary>
public abstract int Id { get; }
/// <summary>
/// Название CSS стиля для отображения
/// </summary>
public abstract string CssClass { get; }
/// <summary>
/// Наименование типа,
/// используется для перенаправления
/// пользователя
/// </summary>
public abstract string TypeName { get; }
/// <summary>
/// Заголовок, отображается в списке autocomplete
/// </summary>
public abstract string Title { get; }
}Я постарался описать в summary всю информацию по свойствам. Надеюсь, всё понятно. Теперь унаследую от этого класса новый класс ExhibitSearch:
/// <summary> /// Класс используется при формировании /// результатов поиска по сущности Exhibit /// </summary> public class ExhibitSearch : SearchItem { Exhibit Model; public ExhibitSearch(Exhibit model) { this.Model = model; } public override int Id { get { return this.Model.Id; } } public override string Title { get { return Model.Title; } } public override string CssClass { get { return "exhibitsearch"; } } public override string TypeName { get { return "экспонат:"; } } }
Обратите внимание на CssClass, я создал этот стиль в файле каскадных стилей. В нем ничего особенного, просто хочется чтобы заголовок был под цвет шаблона в выпадающем списке. Такие стили я создал для каждого из наслеников класса SearchItem. А теперь класс для меток для поиска:
/// <summary> /// Класс используется при формировании /// результатов поиска по сущности Tag /// </summary> public class TagSearch : SearchItem { Tag Model; public TagSearch(Tag model) { this.Model = model; } public override int Id { get { return Model.Id; } } public override string Title { get { return Model.Name; } } public override string CssClass { get { return "tagsearch"; } } public override string TypeName { get { return "метка:"; } } }
И напоследок, остался еще класс для поиска по сущности "Лента":
/// <summary> /// Класс используется при формировании /// результатов поиска по сущности Tag /// </summary> public class LentaSearch : SearchItem { Lenta Model; public LentaSearch(Lenta model) { this.Model = model; } public override int Id { get { return Model.Id; } } public override string Title { get { return Model.Content.CutLongText(100, "..."); } } public override string CssClass { get { return "lentasearch"; } } public override string TypeName { get { return "лента:"; } } }
Пока хватит новых классов. Если потребуется осуществлять поиск по какой-либо еще сущности, я добавлю ее позже.
Метод Search
Возвращаемся к методу поиска:
public JsonResult Search(string term) { List<SearchItem> result = new List<SearchItem>(); var exhibits = exhibitRepository.All.Where(x => x.Title.Contains(term) || x.Content.Contains(term)) .Take(5) .ToList() .Select(x => new ExhibitSearch(x)); if (exhibits.Any()) { result.AddRange(exhibits); } var tags = tagRepository.All .Where(x => x.Name.Contains(term)) .Take(5) .ToList() .Select(x => new TagSearch(x)); if (tags.Any()) { result.AddRange(tags); } var lentas = lentaRepository.All .Where(x => x.Content.Contains(term)) .Take(5) .ToList() .Select(x => new LentaSearch(x)); if (lentas.Any()) { result.AddRange(lentas); } return Json(result.OrderBy(x => x.Title).ToArray(), JsonRequestBehavior.AllowGet); }
Находим все записи в разных типах сущностей, которые подходят по критерию отбора и складываем их в один список (Можно было бы использовать Linq и в частности Uinion(), но я сделал "по старинке"). И если теперь есть метод, можно написать скрипт, который будет его вызывать в файле search.mvc.helpers.js:
$(document).ready(function () { var url = $("#searcher").attr("data-autocomplete"); $("#searcher").autocomplete({ minLength: 2, source: function (request, response) { $.getJSON(url, { term: request.term }, response); }, select: function (event, ui) { block(); if (ui.item.CssClass == 'tagsearch') window.location = '/museum?t=' ui.item.Title; if (ui.item.CssClass == 'exhibitsearch') window.location = '/museum/show/' ui.item.Id; if (ui.item.CssClass == 'lentasearch') window.location = '/lenta?t=' ui.item.Title; return false; } }).data('autocomplete')._renderItem = function (ul, item) { return $('<li style="font-size:.7em; max-width:700px;"></li>') .data('item.autocomplete', item) .append('<a><span class="searchtype">' item.TypeName '</span><span class="searchtitle ' item.CssClass '">' item.Title '</span></a>') .appendTo(ul); }; });
Стоит еще показать как это работает. Autocomplete-поле теперь выбрасывает вот такой спискок:
Я набрал в строке поиска "го" и это результат работы поиска. Мне осталось только предложить скачать проект и попрощаться. Спасибо за внимание - пишите комментарии.
Подробнее: http://feedproxy.google.com/~r/blogmusor/~3/UpMOEN7bMTQ/85
|
Содержание ASP.NET MVC: История одного проекта Готовимся к старту (часть 1)ASP.NET MVC: История одного проекта Всё ради данных (часть 2)ASP.NET MVC: История одного проекта Шаблоны и внешний вид |
РэдЛайн, создание сайта, заказать сайт, разработка сайтов, реклама в Интернете, продвижение, маркетинговые исследования, дизайн студия, веб дизайн, раскрутка сайта, создать сайт компании, сделать сайт, создание сайтов, изготовление сайта, обслуживание сайтов, изготовление сайтов, заказать интернет сайт, создать сайт, изготовить сайт, разработка сайта, web студия, создание веб сайта, поддержка сайта, сайт на заказ, сопровождение сайта, дизайн сайта, сайт под ключ, заказ сайта, реклама сайта, хостинг, регистрация доменов, хабаровск, краснодар, москва, комсомольск |
Дайджест новых статей по интернет-маркетингу на ваш email
Новые статьи и публикации
- 2026-08-25 » Статистика каналов в Максе: почему это важно для вашего бизнеса
- 2026-08-25 » Долгожданный контакт: как появление @AdSupport меняет правила игры в Telegram-рекламе
- 2026-08-25 » Скидка, которая видит покупателя насквозь: как новый инструмент Яндекса превращает бюджет в продажи
- 2026-08-25 » Новая эра телевизионной рекламы: как Яндекс Директ превращает экран в витрину
- 2026-08-25 » Отзывы как двигатель продаж: как обратная связь клиентов продвигает ваш сайт в поиске
- 2026-08-19 » ИИ проверят на соответствие духовно-нравственным ценностям: что это значит для вашего бизнеса
- 2026-08-19 » Маркировка ИИ-контента: что меняется для бизнеса с 1 сентября 2026 года
- 2026-08-19 » Белый список Минцифры: как сайты попадают в перечень и что это значит для вашего бизнеса
- 2026-08-19 » Мобильное приложение Директа получило новые возможности: создание ЕПК и агентский доступ
- 2026-08-19 » Google тестирует новую главную страницу без кнопки поиска: что это значит для вашего бизнеса
- 2026-08-12 » Контент для транспортной компании: какими текстами наполнить сайт, чтобы клиенты выбирали вас
- 2026-08-12 » Сезонность в SEO: как анализировать спрос, не путать падение с катастрофой и готовить сайт к пику продаж
- 2026-08-12 » Семантический поиск: почему плотность ключей умерла и как теперь выводить сайт в топ
- 2026-08-12 » ChatGPT без лимитов: как новая эра искусственного интеллекта меняет правила для вашего бизнеса
- 2026-08-12 » Нейропрофиль VK: как объединение данных пользователей меняет правила таргетинга и продвижения
- 2026-08-03 » Мессенджер «Макс» перестал расходовать мобильный трафик: новый уровень доступности для ваших клиентов
- 2026-08-03 » Яндекс Директ запустил динамический коллтрекинг: как бесплатно оценивать реальные звонки и платить только за результат
- 2026-08-03 » Макс открыл истории для всех пользователей Android: новый канал коммуникации для вашего бизнеса
- 2026-08-03 » Новый инструмент в Яндекс Товарах: как сравнение с похожими бизнесами помогает расти
- 2026-08-03 » Яндекс Вебмастер ускорил обновление данных в Мониторинге запросов: что это значит для вашего бизнеса
- 2026-07-29 » «Адаптация бюджета» в Яндекс Директе: как автоматически масштабировать рекламу без потери эффективности
- 2026-07-29 » Overlay в РСЯ: новый формат мобильной рекламы, который не раздражает пользователей
- 2026-07-29 » «Панорама» в Яндекс Директе: новый уровень охватной рекламы для вашего бизнеса
- 2026-07-29 » Карточки товаров и отзывы на маркетплейсах: что по закону считается рекламой, а что нет
- 2026-07-29 » Комментарии в приватных каналах «Макс»: новый инструмент для бизнес-коммуникаций
- 2026-07-23 » Как ошибки в AI-ответах портят репутацию компании
- 2026-07-23 » Маркировка рекламы в 2026 году: фатальные ошибки, которые обойдутся вашему бизнесу в полмиллиона рублей
- 2026-07-23 » Нейросети в дизайне сайтов и графике: революция, эволюция или угроза?
- 2026-07-23 » РСЯ открыла инструмент авторасстановки рекламы для всех партнеров: как автоматизация меняет правила монетизации
- 2026-07-23 » Контент для стоматологических клиник: какими текстами наполнить сайт, чтобы пациенты записывались сами
Постановка целей, приближение к ним день за днем и, наконец, их достижение — это и есть ключ к счастью Трейси Брайан - - современный американский профессиональный лектор-преподаватель |
Мы создаем сайты, которые работают! Профессионально обслуживаем и продвигаем их , а также по всей России и ближнему зарубежью с 2006 года!
Как мы работаем
Заявка
Позвоните или оставьте заявку на сайте.
Консультация
Обсуждаем что именно Вам нужно и помогаем определить как это лучше сделать!
Договор
Заключаем договор на оказание услуг, в котором прописаны условия и обязанности обеих сторон.
Выполнение работ
Непосредственно оказание требующихся услуг и работ по вашему заданию.
Поддержка
Сдача выполненых работ, последующие корректировки и поддержка при необходимости.

Мы создаем практически любые сайты от продающих страниц до сложных, высоконагруженных и нестандартных веб приложений! Наши сайты это надежные маркетинговые инструменты для успеха Вашего бизнеса и увеличения вашей прибыли! Мы делаем красивые и максимально эффектные сайты по доступным ценам уже много лет!
Комплексный подход это не просто продвижение сайта, это целый комплекс мероприятий, который определяется целями и задачами поставленными перед сайтом и организацией, которая за этим стоит. Время однобоких методов в продвижении сайтов уже прошло, конкуренция слишком высока, чтобы была возможность расслабиться и получать \ удерживать клиентов из Интернета, просто сделав сайт и не занимаясь им...
Мы оказываем полный комплекс услуг по сопровождению сайта: информационному и техническому обслуживанию и развитию Интернет сайтов.
Контекстная реклама - это эффективный инструмент в интернет маркетинге, целью которого является увеличение продаж. Главный плюс контекстной рекламы заключается в том, что она работает избирательно.