Compartir a través de


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.

SearchQryStr

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.

Screenshot that shows the M V C Movie Index page. Local host colon 1 2 3 4 forward slash Movies forward slash index forward slash ghost is in the U R L field and circled in red.

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.

Screenshot that shows the Index dot c s h t m l tab and Solution Explorer open. In Solution Explorer, the subfolder Movies is open and Index dot c s h t m l is selected.

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.

Screenshot that shows the Index page with a title entered into the Title field.

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>"; 
}

SearchPostGhost

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))

BeginFormPost_SM

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.

IndexWithGetURL

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.

Screenshot that shows the Index page. A type of genre is selected.

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.