Поиск

Примечание

Обновленная версия этого руководства доступна здесь с использованием последней версии Visual Studio. В новом руководстве используется ASP.NET Core MVC, который предоставляет множество улучшений по сравнению с этим руководством.

В этом руководстве описывается модель MVC ASP.NET Core с контроллерами и представлениями. Razor Pages — это новая альтернатива в ASP.NET Core, страничной модели программирования, которая упрощает и повышает эффективность создания пользовательского веб-интерфейса. Мы рекомендуем ознакомиться с руководством по Razor Pages до версии MVC. Руководство по Razor Pages:

  • проще для выполнения;
  • охватывает дополнительные возможности;
  • Является предпочтительным подходом для разработки новых приложений.

Добавление метода поиска и представления поиска

В этом разделе вы добавите в метод действия возможность Index поиска, которая позволяет искать фильмы по жанру или имени.

Предварительные требования

Чтобы сопоставить снимки экрана этого раздела, необходимо запустить приложение (F5) и добавить в базу данных следующие фильмы.

Заголовок Дата выпуска Genre Цена
Охотники за привидениями 6/8/1984 Комедия 6,99
Охотники за привидениями II 6/16/1989 Комедия 6,99
Планета обезьян 3/27/1986 Действие 5,99

Обновление формы индекса

Начните с обновления Index метода action до существующего MoviesController класса. Вот этот код:

public ActionResult Index(string searchString) 
{           
    var movies = from m in db.Movies 
                 select m; 
 
    if (!String.IsNullOrEmpty(searchString)) 
    { 
        movies = movies.Where(s => s.Title.Contains(searchString)); 
    } 
 
    return View(movies); 
}

В первой строке Index метода создается следующий запрос LINQ для выбора фильмов:

var movies = from m in db.Movies 
                 select m;

Запрос определен на этом этапе, но еще не был выполнен в базе данных.

searchString Если параметр содержит строку, запрос movies изменяется для фильтрации по значению строки поиска с использованием следующего кода:

if (!String.IsNullOrEmpty(searchString)) 
{ 
    movies = movies.Where(s => s.Title.Contains(searchString)); 
}

Приведенный выше код s => s.Title представляет собой лямбда-выражение. Лямбда-выражения используются в запросах LINQ на основе методов в качестве аргументов для стандартных методов операторов запросов, таких как метод Where , используемый в приведенном выше коде. Запросы LINQ не выполняются при их определении или изменении путем вызова метода, Where например или OrderBy. Вместо этого выполнение запроса откладывается, что означает, что вычисление выражения откладывается до фактического перебора его реализованного значения или ToList вызова метода. Search В примере запрос выполняется в представлении Index.cshtml. Дополнительные сведения об отложенном и немедленном выполнении запросов см. в разделе Выполнение запроса.

Примечание

Метод Contains выполняется в базе данных, а не в приведенном выше коде c#. В базе данных содержит сопоставляется с SQL LIKE, что не учитывает регистр.

Теперь можно обновить Index представление, в котором будет отображаться форма для пользователя.

Запустите приложение и перейдите в папку /Movies/Index. Добавьте в URL-адрес строку запроса, например ?searchString=ghost. Отображаются отфильтрованные фильмы.

SearchQryStr

Если изменить сигнатуру Index метода на параметр с именем id, id параметр будет соответствовать {id} заполнителю маршрутов по умолчанию, заданным в файле App_Start\RouteConfig.cs .

{controller}/{action}/{id}

Исходный Index метод выглядит следующим образом:

public ActionResult Index(string searchString) 
{           
    var movies = from m in db.Movies 
                 select m; 
 
    if (!String.IsNullOrEmpty(searchString)) 
    { 
        movies = movies.Where(s => s.Title.Contains(searchString)); 
    } 
 
    return View(movies); 
}

Измененный Index метод будет выглядеть следующим образом:

public ActionResult Index(string id) 
{ 
    string searchString = id; 
    var movies = from m in db.Movies 
                 select m; 
 
    if (!String.IsNullOrEmpty(searchString)) 
    { 
        movies = movies.Where(s => s.Title.Contains(searchString)); 
    } 
 
    return View(movies); 
}

Теперь можно передать заголовок поиска в качестве данных маршрута (сегмент URL-адреса) вместо значения строки запроса.

Снимок экрана: страница индекса фильма M V C. Локальный двоеточие узла 1 2 3 4 косой черты Фильмы индекс косой черты вперед косой черты призрак находится в поле U R L и обведен красным цветом.

Тем не менее пользователи вряд ли будут каждый раз изменять URL-адрес для поиска фильмов. Итак, теперь вам необходимо добавить пользовательский интерфейс для удобства фильтрации фильмов. Если вы изменили сигнатуру Index метода, чтобы проверить, как передать параметр идентификатора с привязкой к маршруту, измените его так, чтобы Index метод принимает строковый параметр с именем searchString:

public ActionResult Index(string searchString) 
{           
    var movies = from m in db.Movies 
                 select m; 
 
    if (!String.IsNullOrEmpty(searchString)) 
    { 
        movies = movies.Where(s => s.Title.Contains(searchString)); 
    } 
 
    return View(movies); 
}

Откройте файл Views\Movies\Index.cshtml и сразу после @Html.ActionLink("Create New", "Create")добавьте разметку формы, выделенную ниже:

@model IEnumerable<MvcMovie.Models.Movie> 
 
@{ 
    ViewBag.Title = "Index"; 
} 
 
<h2>Index</h2> 
 
<p> 
    @Html.ActionLink("Create New", "Create") 
     
     @using (Html.BeginForm()){    
         <p> Title: @Html.TextBox("SearchString") <br />   
         <input type="submit" value="Filter" /></p> 
        } 
</p>

Вспомогательный Html.BeginForm элемент создает открывающий <form> тег. Вспомогающая Html.BeginForm функция отправляет форму в себя, когда пользователь отправляет форму, нажимая кнопку Фильтр .

Visual Studio 2013 имеет хорошие улучшения при отображении и редактировании файлов представления. При запуске приложения с открытым файлом представления Visual Studio 2013 вызывает правильный метод действия контроллера для отображения представления.

Снимок экрана: вкладка Index dot c h t m l и Обозреватель решений открытой. В Обозреватель решений открыта вложенная папка Фильмы и выбрана точка индекса c h t m l.

Открыв представление индексов в Visual Studio (как показано на рисунке выше), коснитесь Ctr F5 или F5, чтобы запустить приложение, а затем попробуйте найти фильм.

Снимок экрана: страница

Перегрузка метода отсутствует HttpPostIndex . Он не нужен, так как метод не изменяет состояние приложения, а просто фильтрует данные.

Можно добавить следующий метод HttpPost Index. В этом случае вызов действия будет соответствовать методу HttpPost IndexHttpPost Index , и метод будет выполняться, как показано на рисунке ниже.

[HttpPost] 
public string Index(FormCollection fc, string searchString) 
{ 
    return "<h3> From [HttpPost]Index: " + searchString + "</h3>"; 
}

SearchPostGhost

Тем не менее при добавлении этой версии HttpPost метода Index существует ограничение на общую реализацию. Допустим, вам необходимо добавить в закладки конкретный поиск или отправить друзьям ссылку, по которой они могут просмотреть аналогичный отфильтрованный список фильмов. Обратите внимание, что URL-адрес HTTP-запроса POST совпадает с URL-адресом запроса GET (localhost:xxxxx/Movies/Index) — в самом URL-адресе нет сведений о поиске. Сейчас сведения о строке поиска отправляются на сервер в виде значения поля формы. Это означает, что вы не можете записать данные поиска для закладки или отправить друзьям в URL-адресе.

Решение заключается в использовании перегрузки BeginForm , которая указывает, что запрос POST должен добавить сведения о поиске в URL-адрес и что они должны быть перенаправлены в HttpGet версию Index метода . Замените существующий метод без BeginForm параметров следующей разметкой:

@using (Html.BeginForm("Index","Movies",FormMethod.Get))

BeginFormPost_SM

Теперь при отправке поиска URL-адрес содержит строку поискового запроса. Поиск также переносится в метод HttpGet Index, даже если у вас определен метод HttpPost Index.

IndexWithGetURL

Добавление поиска по жанру

Если вы добавили HttpPost версию Index метода, удалите ее сейчас.

Затем вы добавите функцию, которая позволит пользователям искать фильмы по жанру. Замените метод Index следующим кодом:

public ActionResult Index(string movieGenre, string searchString)
{
    var GenreLst = new List<string>();

    var GenreQry = from d in db.Movies
                   orderby d.Genre
                   select d.Genre;

    GenreLst.AddRange(GenreQry.Distinct());
    ViewBag.movieGenre = new SelectList(GenreLst);

    var movies = from m in db.Movies
                 select m;

    if (!String.IsNullOrEmpty(searchString))
    {
        movies = movies.Where(s => s.Title.Contains(searchString));
    }

    if (!string.IsNullOrEmpty(movieGenre))
    {
        movies = movies.Where(x => x.Genre == movieGenre);
    }

    return View(movies);
}

Эта версия Index метода принимает дополнительный параметр, а именно movieGenre. Первые несколько строк кода создают List объект для хранения жанров фильмов из базы данных.

Следующий код определяет запрос LINQ, который извлекает все жанры из базы данных.

var GenreQry = from d in db.Movies 
                   orderby d.Genre 
                   select d.Genre;

Код использует AddRange метод универсальной List коллекции для добавления всех различных жанров в список. (Без модификатора Distinct будут добавлены повторяющиеся жанры— например, комедия будет добавлена дважды в нашем примере). Затем код сохраняет список жанров в объекте ViewBag.MovieGenre . Хранение данных категории (такие жанры фильмов) как объект SelectList в ViewBag, а затем доступ к данным категории в раскрывающемся списке является типичным подходом для приложений MVC.

В следующем коде показано, как проверка параметр .movieGenre Если он не пуст, код дополнительно ограничивает запрос фильмов, чтобы ограничить выбранные фильмы указанным жанром.

if (!string.IsNullOrEmpty(movieGenre))
{
    movies = movies.Where(x => x.Genre == movieGenre);
}

Как было сказано ранее, запрос не выполняется в базе данных до тех пор, пока не будет выполнена итерация списка фильмов (что происходит в представлении после Index возврата метода действия).

Добавление разметки в представление индекса для поддержки поиска по жанрам

Добавьте вспомогателя Html.DropDownList в файл Views\Movies\Index.cshtml непосредственно перед вспомогательным TextBox . Завершенная разметка показана ниже:

@model IEnumerable<MvcMovie.Models.Movie>
@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
    @Html.ActionLink("Create New", "Create")
    @using (Html.BeginForm("Index", "Movies", FormMethod.Get))
    {
    <p>
        Genre: @Html.DropDownList("movieGenre", "All")
        Title: @Html.TextBox("SearchString")
        <input type="submit" value="Filter" />
    </p>
    }
</p>
<table class="table">

В приведенном ниже коде выполняется следующее:

@Html.DropDownList("movieGenre", "All")

Параметр MovieGenre предоставляет ключ для вспомогательного DropDownList средства поиска IEnumerable<SelectListItem> в ViewBag. Объект ViewBag был заполнен в методе действия:

public ActionResult Index(string movieGenre, string searchString)
{
    var GenreLst = new List<string>();

    var GenreQry = from d in db.Movies
                   orderby d.Genre
                   select d.Genre;

    GenreLst.AddRange(GenreQry.Distinct());
    ViewBag.movieGenre = new SelectList(GenreLst);

    var movies = from m in db.Movies
                 select m;

    if (!String.IsNullOrEmpty(searchString))
    {
        movies = movies.Where(s => s.Title.Contains(searchString));
    }

    if (!string.IsNullOrEmpty(movieGenre))
    {
        movies = movies.Where(x => x.Genre == movieGenre);
    }

    return View(movies);
}

Параметр All предоставляет метку параметра. Если проверить этот вариант в браузере, вы увидите, что его атрибут value пуст. Так как наш контроллер фильтрует if только строку не является или пустой null , отправка пустого значения для movieGenre показывает все жанры.

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

ViewBag.movieGenre = new SelectList(GenreLst, "Comedy");

Запустите приложение и перейдите по папке /Movies/Index. Попробуйте выполнить поиск по жанру, по имени фильма и по обоим критериям.

Снимок экрана: страница

В этом разделе вы создали метод действия поиска и представление, которые позволяют пользователям выполнять поиск по названию и жанру фильма. В следующем разделе вы узнаете, как добавить свойство в Movie модель и как добавить инициализатор, который автоматически создаст тестовую базу данных.