Search

Nota:

Hay disponible una versión actualizada de este tutorial con la versión más reciente de Visual Studio. El nuevo tutorial usa ASP.NET Core MVC, que proporciona muchas mejoras en este tutorial.

En este tutorial se enseña 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 la interfaz de usuario web y es más productivo. Se recomienda probar el tutorial de Razor Pages antes de la versión de MVC. Tutorial de Razor Pages:

  • Es más fácil de seguir.
  • Cubre más funcionalidades.
  • Es el enfoque preferido para el desarrollo de aplicaciones nuevas.

Adición de un método de búsqueda y una vista de búsqueda

En esta sección, agregará la funcionalidad de búsqueda al Index método de acción que le permite buscar películas por género o nombre.

Prerrequisitos

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 lanzamiento Género Precio
Cazafantasmas 6/8/1984 Comedia 6,99
Ghostbusters II 6/16/1989 Comedia 6,99
Planeta de los apes 3/27/1986 Acción 5,99

Actualización del formulario de índice

Comience actualizando el Index método de acción a la clase existente MoviesController . 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. En las consultas LINQ basadas en métodos se usan expresiones lambda como argumentos para métodos de operador de consulta estándar, como el método Where del código anterior. Las consultas LINQ no se ejecutan cuando se definen o 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 sobre su valor realizado o se llama al método ToList. En el Search ejemplo, 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, Contiene se asigna a SQL LIKE, que no distingue mayúsculas de 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 cambia la firma del Index método para que tenga un parámetro denominado id, el id parámetro coincidirá con el {id} marcador de posición de las rutas predeterminadas establecidas 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.

Captura de pantalla que muestra la página Índice de películas de M V C. El host local dos puntos 1 2 3 4 barra diagonal Películas barra diagonal Índice barra diagonal ghost está en el campo U R L y está rodeado en rojo.

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 agregará la interfaz de usuario para ayudarles a filtrar películas. Si cambió la firma del método Index para probar cómo pasar el ID del parámetro asociado a la 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 @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 ayudante Html.BeginForm hace que el formulario se envíe a sí mismo cuando el usuario lo envía al hacer clic en el botón Filtrar.

Visual Studio 2013 tiene 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.

Captura de pantalla que muestra la pestaña Index.cshtml y el Explorador de soluciones abiertos. En el Explorador de soluciones, la subcarpeta Movies está abierta y se ha seleccionado Index.cshtml.

Con la vista Índice 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.

Captura de pantalla que muestra la página Índice con un título escrito en el campo Título.

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 como se muestra en la imagen siguiente.

[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. Observe 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 propia dirección 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 HttpGet versión del Index método. Reemplace el método sin BeginForm parámetros 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

Agregar búsqueda por género

Si ha agregado 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, 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 List genérica para agregar todos los géneros distintos a la lista. (Sin el modificador Distinct, se agregarían géneros duplicados; por ejemplo, las comedias se agregarían dos veces en este ejemplo). Después, 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 ViewBagobjeto 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 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, después de que el método de acción Index devuelva).

Agregar etiquetado a la vista del índice para admitir la búsqueda por género

Agregue un Html.DropDownList ayudante al archivo Views\Movies\Index.cshtml, justo antes del TextBox ayudante. 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 DropDownList asistente encuentre un IEnumerable<SelectListItem> en el ViewBag. El ViewBag fue 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. Dado que nuestro controlador solo filtra if, la cadena objetivo no es null ni está vacía; al enviar 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 "Comedia" como opción predeterminada, cambiaría 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.

Captura de pantalla que muestra la página Índice. Se selecciona un tipo de género.

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.