Buscar
Nota:
Hay una versión actualizada de este tutorial, disponible aquí, donde se usa la versión más reciente de Visual Studio. El nuevo tutorial utiliza ASP.NET Core MVC, que proporciona muchas mejoras en comparación con este tutorial.
En este tutorial se muestra ASP.NET Core MVC con controladores y vistas. Razor Pages es una nueva alternativa en ASP.NET Core, un modelo de programación basado en páginas que facilita la creación de interfaces de usuario web y hace que sea más productiva. Se recomienda probar el tutorial de las páginas de Razor antes que la versión MVC. El tutorial de las páginas de Razor:
- Es más fácil de seguir.
- Abarca más características.
- Es el método preferido para el desarrollo de nuevas aplicaciones.
Adición de un método de búsqueda y una vista de búsqueda
En esta sección agregará capacidad de búsqueda para el método de acción Index
que permite buscar películas por género o nombre.
Requisitos previos
Para hacer coincidir las capturas de pantalla de esta sección, debe ejecutar la aplicación (F5) y agregar las siguientes películas a la base de datos.
Título | Fecha de publicación | Género | Precio |
---|---|---|---|
Ghostbusters | 6/8/1984 | Comedia | 6,99 |
Ghostbusters II | 6/16/1989 | Comedia | 6,99 |
Planet of the Apes | 3/27/1986 | Action | 5,99 |
Actualización del formulario de índice
Comience actualizando el método de acción Index
a la clase MoviesController
existente. Este es el código :
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);
}
La primera línea del método Index
crea una consulta LINQ para seleccionar las películas:
var movies = from m in db.Movies
select m;
La consulta se define en este momento, pero aún no se ha ejecutado en la base de datos.
Si el parámetro searchString
contiene una cadena, la consulta de películas se modifica para filtrar según el valor de la cadena de búsqueda:
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
El código s => s.Title
anterior es una expresión Lambda. Las lambdas se usan en consultas LINQ basadas en métodos como argumentos para métodos de operador de consulta estándar, tales como el método Where usado en el código anterior. Las consultas LINQ no se ejecutan cuando se definen o cuando se modifican mediante una llamada a un método, como Where
o OrderBy
. En su lugar, la ejecución de la consulta se aplaza, lo que significa que la evaluación de una expresión se retrasa hasta que se itera realmente su valor realizado o se llama al método ToList
. En el ejemplo Search
, la consulta se ejecuta en la vista Index.cshtml. Para más información sobre la ejecución de consultas en diferido, vea Ejecución de la consulta.
Nota:
El método Contains se ejecuta en la base de datos, no en el código de C# anterior. En la base de datos, Contains se asigna a SQL LIKE, que no distingue mayúsculas y minúsculas.
Ahora puede actualizar la vista Index
que mostrará el formulario al usuario.
Ejecute la aplicación y vaya a /Movies/Index. Anexe una cadena de consulta como ?searchString=ghost
a la dirección URL. Se muestran las películas filtradas.
Si se cambia la firma del método Index
para que tenga un parámetro con el nombre id
, el parámetro id
coincidirá con el marcador de posición {id}
para el conjunto de rutas predeterminado en el archivo App_Start\RouteConfig.cs.
{controller}/{action}/{id}
El método original Index
tiene el siguiente aspecto:
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);
}
El método modificado Index
tendría el siguiente aspecto:
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);
}
Ahora puede pasar el título de la búsqueda como datos de ruta (un segmento de dirección URL) en lugar de como un valor de cadena de consulta.
Sin embargo, no se puede esperar que los usuarios modifiquen la dirección URL cada vez que quieran buscar una película. Por lo tanto, ahora deberá agregar la interfaz de usuario con la que podrán filtrar las películas. Si cambió la firma del método Index
para probar cómo pasar el parámetro ID enlazado a una ruta, vuelva a cambiarlo para que el método Index
tome un parámetro de cadena denominado 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 el archivo Views\Movies\Index.cshtml y, justo después de @Html.ActionLink("Create New", "Create")
, agregue el marcado de formulario resaltado a continuación:
@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>
El asistente Html.BeginForm
crea una etiqueta de apertura <form>
. El asistente Html.BeginForm
hace que el formulario se publique cuando el usuario envía el formulario haciendo clic en el botón Filter.
Visual Studio 2013 cuenta con una buena mejora al mostrar y editar archivos de vista. Al ejecutar la aplicación con un archivo de vista abierto, Visual Studio 2013 invoca el método de acción de controlador correcto para mostrar la vista.
Con la vista Index abierta en Visual Studio (como se muestra en la imagen anterior), pulse Ctr F5 o F5 para ejecutar la aplicación y, a continuación, intente buscar una película.
No hay ninguna sobrecarga HttpPost
del método Index
. No es necesario, porque el método no cambia el estado de la aplicación, simplemente filtra los datos.
Después, puede agregar el método HttpPost Index
siguiente. En ese caso, el invocador de acción coincidiría con el método HttpPost Index
, mientras que el método HttpPost Index
se ejecutaría tal como se muestra en la imagen de abajo.
[HttpPost]
public string Index(FormCollection fc, string searchString)
{
return "<h3> From [HttpPost]Index: " + searchString + "</h3>";
}
Sin embargo, aunque agregue esta versión de HttpPost
al método Index
, hay una limitación en cómo se ha implementado todo esto. Supongamos que quiere marcar una búsqueda en particular o que quiere enviar un vínculo a sus amigos donde puedan hacer clic para ver la misma lista filtrada de películas. Tenga en cuenta que la dirección URL de la solicitud HTTP POST es la misma que la dirección URL de la solicitud GET (localhost:xxxxx/Movies/Index); no hay información de búsqueda en la URL. En este momento, la información de la cadena de búsqueda se envía al servidor como un valor de campo de formulario. Esto significa que no se puede capturar esa información de búsqueda para marcar o enviar a amigos en una dirección URL.
La solución consiste en usar una sobrecarga de BeginForm
que especifica que la solicitud POST debe agregar la información de búsqueda a la dirección URL y que se debe enrutar a la versión HttpGet
del método Index
. Reemplace el método sin parámetros BeginForm
existente por el marcado siguiente:
@using (Html.BeginForm("Index","Movies",FormMethod.Get))
Ahora, cuando se envía una búsqueda, la URL contiene la cadena de consulta de búsqueda. La búsqueda también será dirigida al método de acción HttpGet Index
, aunque tenga un método HttpPost Index
.
Adición de búsqueda por género
Si agregó la versión HttpPost
del método Index
, elimínela ahora.
A continuación, agregará una característica para permitir que los usuarios busquen películas por género. Reemplace el método Index
con el código siguiente:
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 versión del método Index
toma un parámetro adicional, a saber movieGenre
. Las primeras líneas de código crean un objeto List
para contener géneros de películas de la base de datos.
El código siguiente es una consulta LINQ que recupera todos los géneros de la base de datos.
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
El código usa el método AddRange
de la colección genérica List
para agregar todos los géneros distintos a la lista. (Sin el modificador Distinct
, se agregarían géneros duplicados; por ejemplo, la comedia se agregaría dos veces en nuestra muestra). A continuación, el código almacena la lista de géneros en el objeto ViewBag.MovieGenre
. Almacenar datos de categoría (como géneros de películas) como un objeto SelectList en un ViewBag
y, a continuación, acceder a los datos de categoría en un cuadro de lista desplegable es un enfoque típico para las aplicaciones MVC.
En el código siguiente se muestra cómo comprobar el parámetro movieGenre
. Si no está vacío, el código restringe aún más la consulta de películas para limitar las películas seleccionadas al género especificado.
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
Como se indicó anteriormente, la consulta no se ejecuta en la base de datos hasta que se itera la lista de películas (que sucede en la vista, tras la devolución del método de acción Index
).
Adición de marcado a la vista Index para admitir la búsqueda por género
Agregue un asistente Html.DropDownList
al archivo Views\Movies\Index.cshtml, justo antes del asistente TextBox
. A continuación se muestra el marcado completado:
@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">
En el código siguiente:
@Html.DropDownList("movieGenre", "All")
El parámetro "MovieGenre" proporciona la clave para que el asistente DropDownList
encuentre un elemento IEnumerable<SelectListItem>
en ViewBag
. ViewBag
se ha rellenado en el método de acción:
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);
}
El parámetro "All" proporciona una etiqueta de opción. Si inspecciona esa opción en el explorador, verá que su atributo "value" está vacío. Como nuestro controlador solo filtra if
la cadena no es null
o está vacía, si se envía un valor vacío para movieGenre
, se muestran todos los géneros.
También puede establecer una opción para que se seleccione de forma predeterminada. Si quisiera "Comedy" como opción predeterminada, tendría que cambiar el código en el controlador de la siguiente manera:
ViewBag.movieGenre = new SelectList(GenreLst, "Comedy");
Ejecute la aplicación y vaya a /Movies/Index. Pruebe una búsqueda por género, por nombre de película y por ambos criterios.
En esta sección ha creado un método de acción de búsqueda y una vista que permiten a los usuarios buscar por título y género de películas. En la sección siguiente, verá cómo agregar una propiedad al modelo Movie
y cómo agregar un inicializador que creará automáticamente una base de datos de prueba.