Pesquisar
Observação
Uma versão atualizada deste tutorial está disponível aqui usando a versão mais recente do Visual Studio. O novo tutorial usa ASP.NET Core MVC, que fornece muitas melhorias ao longo deste tutorial.
Este tutorial ensina a usar o ASP.NET Core MVC com controladores e exibições. O Razor Pages é uma nova alternativa no ASP.NET Core, um modelo de programação baseado em página que torna a criação da interface do usuário da Web mais fácil e produtiva. Recomendamos que você experimente o tutorial do Razor Pages antes da versão do MVC. O tutorial Páginas do Razor:
- É mais fácil de acompanhar.
- Aborda mais recursos.
- É a abordagem preferencial para o desenvolvimento de novos aplicativos.
Adicionando um método de pesquisa e uma exibição de pesquisa
Nesta seção, você adicionará a funcionalidade de pesquisa ao Index
método de ação que permite pesquisar filmes por gênero ou nome.
Pré-requisitos
Para corresponder às capturas de tela desta seção, você precisa executar o aplicativo (F5) e adicionar os filmes a seguir ao banco de dados.
Title | Data de lançamento | Gênero | Preço |
---|---|---|---|
Ghostbusters | 6/8/1984 | Comédia | 6,99 |
Caça-Fantasmas II | 6/16/1989 | Comédia | 6,99 |
Planeta dos Macacos | 3/27/1986 | Ação | 5,99 |
Atualizando o formulário de índice
Comece atualizando o método de Index
ação para a classe existente MoviesController
. O código é o seguinte:
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);
}
A primeira linha do Index
método cria a seguinte consulta LINQ para selecionar os filmes:
var movies = from m in db.Movies
select m;
A consulta é definida neste ponto, mas ainda não foi executada no banco de dados.
Se o searchString
parâmetro contiver uma cadeia de caracteres, a consulta movies será modificada para filtrar o valor da cadeia de caracteres de pesquisa, usando o seguinte código:
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
O código s => s.Title
acima é uma Expressão Lambda. Lambdas são usados em consultas LINQ baseadas em método como argumentos para métodos de operador de consulta padrão, como o método Where usado no código acima. As consultas LINQ não são executadas quando são definidas ou quando são modificadas chamando um método como Where
ou OrderBy
. Em vez disso, a execução da consulta é adiada, o que significa que a avaliação de uma expressão é atrasada até que seu valor realizado seja iterado ou o ToList
método seja chamado. Search
No exemplo, a consulta é executada na exibição Index.cshtml. Para obter mais informações sobre a execução de consulta adiada, consulte Execução da consulta.
Observação
O método Contains é executado no banco de dados, não no código c# acima. No banco de dados, Contém mapas para SQL LIKE, que não diferencia maiúsculas de minúsculas.
Agora você pode atualizar o Index
modo de exibição que exibirá o formulário para o usuário.
Execute o aplicativo e navegue até /Movies/Index. Acrescente uma cadeia de consulta, como ?searchString=ghost
, à URL. Os filmes filtrados são exibidos.
Se você alterar a assinatura do Index
método para ter um parâmetro chamado id
, o id
parâmetro corresponderá ao {id}
espaço reservado para as rotas padrão definidas no arquivo App_Start\RouteConfig.cs .
{controller}/{action}/{id}
O método original Index
tem esta aparência:
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);
}
O método modificado Index
teria a seguinte aparência:
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);
}
Agora você pode passar o título de pesquisa como dados de rota (um segmento de URL), em vez de como um valor de cadeia de consulta.
No entanto, você não pode esperar que os usuários modifiquem a URL sempre que desejarem pesquisar um filme. Portanto, agora você adicionará uma interface do usuário para ajudá-los a filtrar os filmes. Se você alterou a assinatura do Index
método para testar como passar o parâmetro de ID associada à rota, altere-o de volta para que o Index
método use um parâmetro de cadeia de caracteres chamado 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);
}
Abra o arquivo Views\Movies\Index.cshtml e, logo após @Html.ActionLink("Create New", "Create")
, adicione a marcação de formulário realçada abaixo:
@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>
O Html.BeginForm
auxiliar cria uma marca de abertura <form>
. O Html.BeginForm
auxiliar faz com que o formulário seja postado para si mesmo quando o usuário envia o formulário clicando no botão Filtrar .
Visual Studio 2013 tem uma boa melhoria ao exibir e editar Exibir arquivos. Quando você executa o aplicativo com um arquivo de exibição aberto, Visual Studio 2013 invoca o método de ação do controlador correto para exibir a exibição.
Com a exibição Índice aberta no Visual Studio (conforme mostrado na imagem acima), toque em Ctr F5 ou F5 para executar o aplicativo e tente pesquisar um filme.
Não há HttpPost
sobrecarga do Index
método . Você não precisa dele, pois o método não está alterando o estado do aplicativo, apenas filtrando dados.
Você poderá adicionar o método HttpPost Index
a seguir. Nesse caso, o invocador de ação corresponderia ao HttpPost Index
método e o HttpPost Index
método seria executado conforme mostrado na imagem abaixo.
[HttpPost]
public string Index(FormCollection fc, string searchString)
{
return "<h3> From [HttpPost]Index: " + searchString + "</h3>";
}
No entanto, mesmo se você adicionar esta versão HttpPost
do método Index
, haverá uma limitação na forma de como isso tudo foi implementado. Imagine que você deseja adicionar uma pesquisa específica como Favoritos ou enviar um link para seus amigos para que eles possam clicar para ver a mesma lista filtrada de filmes. Observe que a URL da solicitação HTTP POST é a mesma que a URL para a solicitação GET (localhost:xxxxx/Movies/Index) – não há nenhuma informação de pesquisa na URL em si. No momento, as informações da cadeia de caracteres de pesquisa são enviadas ao servidor como um valor de campo de formulário. Isso significa que você não pode capturar essas informações de pesquisa para marcar ou enviar para amigos em uma URL.
A solução é usar uma sobrecarga de BeginForm
que especifica que a solicitação POST deve adicionar as informações de pesquisa à URL e que ela deve ser roteada para a HttpGet
versão do Index
método. Substitua o método sem BeginForm
parâmetros existente pela seguinte marcação:
@using (Html.BeginForm("Index","Movies",FormMethod.Get))
Agora, quando você envia uma pesquisa, a URL contém uma cadeia de caracteres de consulta de pesquisa. A pesquisa também irá para o método de ação HttpGet Index
, mesmo se você tiver um método HttpPost Index
.
Adicionando Pesquisa por Gênero
Se você adicionou a HttpPost
versão do método , exclua-a Index
agora.
Em seguida, você adicionará um recurso para permitir que os usuários pesquisem filmes por gênero. Substitua o método Index
pelo seguinte código:
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);
}
Esta versão do Index
método usa um parâmetro adicional, ou movieGenre
seja, . As primeiras linhas de código criam um List
objeto para conter gêneros de filme do banco de dados.
O código a seguir é uma consulta LINQ que recupera todos os gêneros do banco de dados.
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
O código usa o AddRange
método da coleção genérica List
para adicionar todos os gêneros distintos à lista. (Sem o Distinct
modificador, gêneros duplicados seriam adicionados — por exemplo, comédia seria adicionada duas vezes em nossa amostra). Em seguida, o código armazena a lista de gêneros no ViewBag.MovieGenre
objeto . Armazenar dados de categoria (gêneros de filme) como um objeto SelectList em um ViewBag
, acessar os dados de categoria em uma caixa de listagem suspensa é uma abordagem típica para aplicativos MVC.
O código a seguir mostra como marcar o movieGenre
parâmetro . Se não estiver vazio, o código restringirá ainda mais a consulta de filmes para limitar os filmes selecionados ao gênero especificado.
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
Conforme mencionado anteriormente, a consulta não é executada no banco de dados até que a lista de filmes seja iterada (o que acontece no Modo de Exibição, após o retorno do método de ação Index
).
Adicionando marcação à exibição de índice para dar suporte à pesquisa por gênero
Adicione um Html.DropDownList
auxiliar ao arquivo Views\Movies\Index.cshtml , pouco antes do TextBox
auxiliar. A marcação concluída é mostrada abaixo:
@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">
No seguinte código:
@Html.DropDownList("movieGenre", "All")
O parâmetro "MovieGenre" fornece a chave para o DropDownList
auxiliar encontrar um IEnumerable<SelectListItem>
no ViewBag
. O ViewBag
foi preenchido no método de ação:
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);
}
O parâmetro "Todos" fornece um rótulo de opção. Se você inspecionar essa escolha no navegador, verá que o atributo "valor" dele está vazio. Como nosso controlador filtra apenas a cadeia de caracteres if
não null
está ou vazia, enviar um valor vazio para movieGenre
mostra todos os gêneros.
Você também pode definir uma opção para ser selecionada por padrão. Se você quisesse "Comédia" como sua opção padrão, alteraria o código no Controlador da seguinte maneira:
ViewBag.movieGenre = new SelectList(GenreLst, "Comedy");
Execute o aplicativo e navegue até /Movies/Index. Experimente uma pesquisa por gênero, por nome de filme e por ambos os critérios.
Nesta seção, você criou um método de ação de pesquisa e exibição que permite que os usuários pesquisem por título e gênero de filme. Na próxima seção, você verá como adicionar uma propriedade ao Movie
modelo e como adicionar um inicializador que criará automaticamente um banco de dados de teste.