Introducción a ASP.NET Web Pages: aspectos básicos del formulario HTML

Por Tom FitzMacken

En este tutorial, se muestran los aspectos básicos sobre cómo crear un formulario de entrada y cómo controlar la entrada de usuario al usar ASP.NET Web Pages (Razor). Y ahora que tiene una base de datos, usará sus aptitudes para formularios para permitir que los usuarios encuentren películas específicas en la base de datos. Se da por supuesto que ha completado la serie en Introducción a la visualización de datos mediante ASP.NET Web Pages.

Temas que se abordarán:

  • Cómo crear un formulario mediante elementos HTML estándar.
  • Cómo leer la entrada de usuario en un formulario.
  • Cómo crear una consulta SQL que obtiene datos de forma selectiva mediante un término de búsqueda que proporciona el usuario.
  • Cómo hacer que los campos de la página "recuerden" lo que escribió el usuario.

Características y tecnologías descritas:

  • Objeto Request.
  • La cláusula Where de SQL.

Lo que creará

En el tutorial anterior, ha creado una base de datos, ha agregado datos y, a continuación, ha usado el asistente WebGrid para mostrar los datos. En este tutorial, agregará un cuadro de búsqueda que le permitirá encontrar películas de un género específico o cuyo título contenga cualquier palabra que escriba. (Por ejemplo, podrá encontrar todas las películas cuyo género sea "Acción" o cuyo título contenga "Harry" o "Aventura").

Cuando haya terminado este tutorial, tendrá una página como esta:

Movies page with Genre and Title search

La parte de la lista de la página es la misma que en el último tutorial: una cuadrícula. La diferencia será que la cuadrícula solo mostrará las películas que ha buscado.

Acerca de los formularios HTML

(Si tiene experiencia en la creación de formularios HTML y en la diferencia entre GET y POST, puede omitir esta sección).

Un formulario tiene elementos de entrada de usuario: cuadros de texto, botones, botones de radio, casillas, listas desplegables, etc. Los usuarios rellenan estos controles o realizan selecciones y, a continuación, envían el formulario haciendo clic en un botón.

En este ejemplo, se muestra la sintaxis básica de HTML para un formulario:

<form method="post">
  <input type="text" name="name" value="" />
  <br/>
  <input type="submit" name="submit" value="Submit" />
</form>

Cuando se ejecuta este marcado en una página, se crea un formulario sencillo que tiene el siguiente aspecto:

Basic HTML form as rendered in the browser

El elemento <form> incluye los elementos HTML que se van a enviar. (Un error fácil de cometer es agregar elementos a la página, pero luego olvidar colocarlos dentro de un elemento <form>. En ese caso, no se envía nada). El atributo method indica al explorador cómo enviar la entrada de usuario. Establézcalo en post si va a realizar una actualización en el servidor o en get si solo va a recuperar datos del servidor.

Sugerencia

GET, POST y seguridad de los verbos HTTP

HTTP, el protocolo que usan los exploradores y los servidores para intercambiar información, es notablemente sencillo en sus operaciones básicas. Los exploradores usan solo algunos verbos para realizar solicitudes a los servidores. Al escribir código para la web, resulta útil comprender estos verbos y cómo los usan el explorador y el servidor. Con diferencia, los verbos más utilizados son estos:

  • GET. El explorador usa este verbo para recuperar algo del servidor. Por ejemplo, al escribir una dirección URL en el explorador, este realiza una operación GET para solicitar la página que desee. Si la página incluye gráficos, el explorador realiza operaciones GET adicionales para obtener las imágenes. Si la operación GET tiene que pasar información al servidor, se pasa como parte de la dirección URL en la cadena de consulta.
  • POST. El explorador envía una solicitud POST para enviar datos que se van a agregar o cambiar en el servidor. Por ejemplo, el verbo POST se usa para crear registros en una base de datos o cambiar los existentes. La mayoría de las veces, al rellenar un formulario y hacer clic en el botón Enviar, el explorador realiza una operación POST. En una operación POST, los datos que se pasan al servidor se encuentran en el cuerpo de la página.

Una distinción importante entre estos verbos es que no se supone que una operación GET cambie nada en el servidor, o para expresarlo de una manera ligeramente más abstracta, una operación GET no da lugar a un cambio de estado en el servidor. Puede realizar una operación GET en los mismos recursos tantas veces como desee y esos recursos no cambian. (A menudo se dice que una operación GET es "segura" o mediante un término técnico es idempotente). Por el contrario, una solicitud POST cambia algo en el servidor cada vez que realiza la operación.

Dos ejemplos ayudarán a ilustrar esta distinción. Cuando realiza una búsqueda mediante un motor como Bing o Google, rellena un formulario que consta de un cuadro de texto y, a continuación, hace clic en el botón de búsqueda. El explorador realiza una operación GET en la que se pasa el valor especificado en el cuadro como parte de la dirección URL. El uso de una operación GET para este tipo de formulario es correcto, ya que una operación de búsqueda no cambia ningún recurso en el servidor, solo recupera información.

Ahora, piense en el proceso de hacer un pedido en línea. Se rellenan los detalles del pedido y, a continuación, se hace clic en el botón Enviar. Esta operación será una solicitud POST, ya que la operación dará lugar a cambios en el servidor, como un nuevo registro de pedido, un cambio en la información de la cuenta y quizás muchos otros cambios. A diferencia de la operación GET, no puede repetir la solicitud POST; si lo hace, cada vez que se reenvía la solicitud, se generaría un nuevo pedido en el servidor. (En casos como este, los sitios web a menudo le advertirán de que no haga clic en un botón de envío más de una vez, o se deshabilitará el botón de envío para que no vuelva a enviar el formulario accidentalmente).

En el transcurso de este tutorial, usará una operación GET y una operación POST para trabajar con formularios HTML. Explicaremos en cada caso por qué el verbo que usa es el adecuado.

(Para obtener más información sobre los verbos HTTP, consulte el artículo Definiciones de método en el sitio web de W3C).

La mayoría de los elementos de entrada de usuario son elementos <input> de HTML. Tienen un aspecto similar a <input type="type" name="name">,, donde type indica el tipo de control de entrada de usuario que desea. Estos son los elementos comunes:

  • Cuadro de texto: <input type="text">
  • Casilla: <input type="check">
  • Botón de radio: <input type="radio">
  • Botón: <input type="button">
  • Botón Enviar: <input type="submit">

También puede usar el elemento <textarea> para crear un cuadro de texto de varias líneas y el elemento <select> para crear una lista desplegable o una lista desplazable. (Para obtener más información sobre los elementos de un formulario HTML, consulte Formularios y entrada en HTML en el sitio web de W3Schools).

El atributo name es muy importante, ya que con el nombre es cómo obtendrá el valor del elemento más adelante, como verá en breve.

La parte interesante es lo que el desarrollador de las páginas hace con la entrada del usuario. No hay ningún comportamiento integrado asociado a estos elementos. En su lugar, debe obtener los valores que el usuario ha especificado o seleccionado y hacer algo con ellos. Eso es lo que aprenderá en este tutorial.

Sugerencia

HTML5 y formularios de entrada

Como es posible que sepa, HTML está en transición y la versión más reciente (HTML5) incluye compatibilidad con formas más intuitivas para que los usuarios escriban la información. Por ejemplo, en HTML5, usted (el desarrollador de páginas) puede indicar a la página que desea que el usuario escriba una fecha. A continuación, el explorador puede mostrar automáticamente un calendario en lugar de exigir al usuario que escriba una fecha manualmente. Sin embargo, HTML5 es nuevo y aún no se admite en todos los exploradores.

ASP.NET Web Pages admite la entrada HTML5 en la medida en que lo haga el explorador del usuario. Para obtener una idea de los nuevos atributos del elemento <input> en HTML5, consulte Atributo <input > type de HTML en el sitio web de W3Schools.

Crear el formulario

En WebMatrix, en el área de trabajo Archivos, abra la página Movies.cshtml.

Después de la etiqueta de cierre </h1> y antes de la etiqueta de apertura <div> de la llamada a grid.GetHtml, agregue el marcado siguiente:

<form method="get">
  <div>
    <label for="searchGenre">Genre to look for:</label>
    <input type="text" name="searchGenre" value="" />
    <input type="Submit" value="Search Genre" /><br/>
    (Leave blank to list all movies.)<br/>
    </div>
</form>

Este marcado crea un formulario que tiene un cuadro de texto llamado searchGenre y un botón Enviar. El cuadro de texto y el botón Enviar se incluyen en un elemento <form> cuyo atributo method está establecido en get. (Recuerde que si no coloca el cuadro de texto y el botón Enviar dentro de un elemento <form>, no se enviará nada al hacer clic en el botón). El verbo GET se usa aquí porque está creando un formulario que no realiza ningún cambio en el servidor, simplemente da como resultado una búsqueda. (En el tutorial anterior, usó un método post, que es como se envían los cambios al servidor. Lo verá de nuevo en el siguiente tutorial).

Ejecute la página. Aunque no ha definido ningún comportamiento para el formulario, puede ver que tiene el aspecto siguiente:

Movies page with search box for Genre

Escriba un valor en el cuadro de texto, como "Comedia". A continuación, haga clic en Search Genre.

Tome nota de la dirección URL de la página. Dado que se establece el atributo method del elemento <form> en get, el valor que especificó ahora forma parte de la cadena de consulta en la dirección URL, de la siguiente manera:

http://localhost:45661/Movies.cshtml?searchGenre=Comedy

Lectura de los valores del formulario

La página ya contiene código que obtiene datos de la base de datos y muestra los resultados en una cuadrícula. Ahora, tiene que agregar código que lea el valor del cuadro de texto para poder ejecutar una consulta SQL que incluya el término de búsqueda.

Dado que se establece el método del formulario en get, puede leer el valor que se especificó en el cuadro de texto mediante el uso de código similar al siguiente:

var searchTerm = Request.QueryString["searchGenre"];

El objeto Request.QueryString (la propiedad QueryString del objeto Request) incluye los valores de los elementos que se enviaron como parte de la operación GET. La propiedad Request.QueryString contiene una colección (una lista) de los valores que se envían en el formulario. Para obtener cualquier valor individual, especifique el nombre del elemento que desee. Por eso tiene que tener un atributo name en el elemento <input> (searchTerm) que crea el cuadro de texto. (Para obtener más información sobre el objeto Request, consulte la barra lateral más adelante).

Es lo suficientemente sencillo como para leer el valor del cuadro de texto. Pero si el usuario no ha escrito nada en el cuadro de texto, pero ha hecho clic en Search de todos modos, puede omitir ese clic, ya que no hay nada que buscar.

El código siguiente es un ejemplo que muestra cómo implementar estas condiciones. (Aún no tiene que agregar este código; lo hará en un momento).

if(!Request.QueryString["searchGenre"].IsEmpty() ) {
     // Do something here
}

La prueba se desglosa de esta manera:

  • Obtener el valor de Request.QueryString["searchGenre"], es decir, el valor que se especificó en el elemento <input> llamado searchGenre.
  • Averiguar si está vacío mediante el método IsEmpty. Este método es la manera estándar de determinar si algo (por ejemplo, un elemento del formulario) contiene un valor. Pero realmente, solo importa si no está vacío, por lo tanto...
  • Agregue el operador ! delante de la prueba IsEmpty. (El operador ! significa NOT lógico).

En lenguaje sin formato, toda la condición if se traduce en lo siguiente: Si el elemento searchGenre del formulario no está vacío, ...

Este bloque establece la fase para crear una consulta que usa el término de búsqueda. Lo hará en la sección siguiente.

Sugerencia

Objeto Request

El objeto Request contiene toda la información que el explorador envía a la aplicación cuando se solicita o envía una página. Este objeto incluye cualquier información que proporcione el usuario, como los valores de los cuadros de texto o un archivo que se va a cargar. También incluye todo tipo de información adicional, como las cookies, los valores de la cadena de consulta de la dirección URL (si existe), la ruta de acceso del archivo de la página que se está ejecutando, el tipo de explorador que está usando el usuario, la lista de idiomas que se ha establecido en el explorador y mucho más.

El objeto Request es una colección (lista) de valores. Para obtener un valor individual de la colección, especifique su nombre:

var someValue = Request["name"];

El objeto Request expone realmente varios subconjuntos. Por ejemplo:

  • Request.Form proporciona los valores de los elementos que hay dentro del elemento <form> enviado si la solicitud es una solicitud POST.
  • Request.QueryString proporciona solo los valores de la cadena de consulta de la dirección URL. (En una dirección URL como http://mysite/myapp/page?searchGenre=action&page=2, la sección ?searchGenre=action&page=2 de la dirección URL es la cadena de consulta).
  • La colección Request.Cookies le proporciona acceso a las cookies enviadas por el navegador.

Para obtener un valor que se sabe que está en el formulario enviado, puede usar Request["name"]. Como alternativa, puede usar las versiones más específicas: Request.Form["name"] (para solicitudes POST) o Request.QueryString["name"] (para solicitudes GET). Por supuesto, name es el nombre del elemento que se va a obtener.

El nombre del elemento que desea obtener debe ser único dentro de la colección que está usando. Por eso el objeto Request proporciona los subconjuntos como Request.Form y Request.QueryString. Supongamos que la página contiene un elemento de formulario llamado userName y también contiene una cookie llamada userName. Si obtiene Request["userName"], es ambiguo si desea el valor del formulario o la cookie. Sin embargo, si obtiene Request.Form["userName"] o Request.Cookie["userName"], está siendo explícito sobre qué valor se va a obtener.

Es recomendable ser específico y usar el subconjunto de Request que le interesa, como Request.Form o Request.QueryString. En el caso de las páginas sencillas que está creando en este tutorial, probablemente no marca ninguna diferencia. Sin embargo, a medida que cree páginas más complejas, el uso de la versión explícita Request.Form o Request.QueryString puede ayudarle a evitar problemas que pueden surgir cuando la página contiene un formulario (o varios formularios), cookies, valores de cadena de consulta, etc.

Creación de una consulta mediante un término de búsqueda

Ahora que sabe cómo obtener el término de búsqueda especificado por el usuario, puede crear una consulta que lo use. Recuerde que para obtener todos los elementos de película de la base de datos, está usando una consulta SQL similar a esta instrucción:

SELECT * FROM Movies

Para obtener solo determinadas películas, debe usar una consulta que incluya una cláusula Where. Esta cláusula le permite establecer una condición sobre qué filas devuelve la consulta. Este es un ejemplo:

SELECT * FROM Movies WHERE Genre = 'Action'

El formato básico es WHERE column = value. Puede usar operadores diferentes además de simplemente =, como > (mayor que), < (menor que), <> (no igual a), <= (menor o igual que), etc., dependiendo de lo que esté buscando.

Por si se lo está preguntando, las instrucciones SQL no distinguen mayúsculas de minúsculas, SELECT es lo mismo que Select (o incluso que select). Sin embargo, las personas suelen poner en mayúsculas las palabras clave de una instrucción SQL, como SELECT y WHERE, para facilitar la lectura.

Paso del término de búsqueda como parámetro

Buscar un género específico es lo suficientemente fácil (WHERE Genre = 'Action'), pero querrá poder buscar cualquier género que escriba el usuario. Para ello, cree una consulta SQL que incluya un marcador de posición para el valor que se va a buscar. Tendrá un aspecto similar al siguiente comando:

SELECT * FROM Movies WHERE Genre = @0

El marcador de posición es el carácter @ seguido de cero. Como podría adivinar, una consulta puede contener varios marcadores de posición y se llamarán @0, @1, @2, etc.

Para configurar la consulta y pasarla realmente el valor, use código como el siguiente:

selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
selectedData = db.Query(selectCommand, Request.QueryString["searchGenre"]);

Este código es similar al que ya ha hecho para mostrar los datos en la cuadrícula. Las únicas diferencias son:

  • La consulta contiene un marcador de posición (WHERE Genre = @0").
  • La consulta se coloca en una variable (selectCommand); antes, pasó la consulta directamente al método db.Query.
  • Al llamar al método db.Query, se pasan la consulta y el valor que se va a usar para el marcador de posición. (Si la consulta tuviera varios marcadores de posición, los pasaría como valores independientes al método).

Si reúne todos estos elementos, obtendrá el código siguiente:

if(!Request.QueryString["searchGenre"].IsEmpty() ) { 
    searchTerm = Request.QueryString["searchGenre"];
    selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
    selectedData = db.Query(selectCommand, searchTerm);
}

Nota:

Importante: El uso de marcadores de posición (como @0) para pasar valores a un comando SQL es muy importante para la seguridad. La forma que se ve aquí, con marcadores de posición para los datos variables, es la única manera en la que debe construir comandos SQL.

Nunca construya una instrucción SQL mediante la agrupación (concatenación) de texto literal y los valores que obtiene del usuario. La concatenación de entradas de usuario en una instrucción SQL abre el sitio a un ataque por inyección de código SQL, donde un usuario malintencionado envía valores a la página que hackean la base de datos. (Puede leer más en el artículo Inyección de código SQL en el sitio web de MSDN).

Actualización de la página Movies con código de búsqueda

Ahora, puede actualizar el código del archivo Movies.cshtml. Para empezar, reemplace el código del bloque de código de la parte superior de la página por este código:

var db = Database.Open("WebPagesMovies");
var selectCommand = "SELECT * FROM Movies";
var searchTerm = "";

La diferencia aquí es que ha colocado la consulta en la variable selectCommand, que pasará a db.Query más adelante. Colocar la instrucción SQL en una variable le permite cambiar la instrucción, que es lo que hará para realizar la búsqueda.

También ha quitado estas dos líneas, que volverá a colocar más adelante:

var selectedData = db.Query("SELECT * FROM Movies");
var grid = new WebGrid(source: selectedData, rowsPerPage: 3);

Todavía no quiere ejecutar la consulta (es decir, llamar a db.Query) y tampoco quiere inicializar aún el asistente WebGrid. Hará esas cosas después de averiguar qué instrucción SQL tiene que ejecutarse.

Después de este bloque reescrito, puede agregar la nueva lógica para controlar la búsqueda. El código completo tendrá un aspecto similar al del ejemplo siguiente. Actualice el código de la página para que coincida con este ejemplo:

@{
    var db = Database.Open("WebPagesMovies") ;
    var selectCommand = "SELECT * FROM Movies";
    var searchTerm = "";

    if(!Request.QueryString["searchGenre"].IsEmpty() ) {
        selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
        searchTerm = Request.QueryString["searchGenre"];
    }

    var selectedData = db.Query(selectCommand, searchTerm);
    var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3);
}

La página ahora funciona así. Cada vez que se ejecuta la página, el código abre la base de datos y la variable selectCommand se establece en la instrucción SQL que obtiene todos los registros de la tabla Movies. El código también inicializa la variable searchTerm.

Sin embargo, si la solicitud actual incluye un valor para el elemento searchGenre, el código establece selectCommand en una consulta diferente, es decir, en una que incluya la cláusula Where para buscar un género. También establece searchTerm en lo que se pasó para el cuadro de búsqueda (que podría no ser nada).

Independientemente de la instrucción SQL que haya en selectCommand, el código llama a db.Query para ejecutar la consulta, pasando lo que sea en searchTerm. Si no hay nada en searchTerm, no importa, porque en ese caso no hay ningún parámetro para pasar el valor a selectCommand de todos modos.

Por último, el código inicializa el asistente WebGrid mediante el uso de los resultados de la consulta, al igual que antes.

Puede ver que colocando la instrucción SQL y el término de búsqueda en variables, ha agregado flexibilidad al código. Como verá más adelante en este tutorial, puede usar este marco básico y seguir agregando lógica para diferentes tipos de búsquedas.

Prueba de la característica de búsqueda por género

En WebMatrix, ejecute la página Movies.cshtml. Verá la página con el cuadro de texto del género.

Escriba un género que haya especificado para uno de los registros de prueba y, a continuación, haga clic en Search. Esta vez verá una lista solo de las películas que coinciden con ese género:

Movies page listing after searching for genre 'Comedies'

Escriba otro género y vuelva a buscar. Pruebe a escribir el género usando todas las letras minúsculas o mayúsculas para que pueda ver que la búsqueda no distingue mayúsculas de minúsculas.

"Recordar" lo que escribió el usuario

Es posible que haya observado que después de escribir un género y hacer clic en Search Genre, apareció una lista para ese género. Sin embargo, el cuadro de texto de búsqueda estaba vacío; es decir, no recordó lo que había escrito.

Es importante comprender por qué se produce este comportamiento. Al enviar una página, el explorador envía una solicitud al servidor web. Cuando ASP.NET obtiene la solicitud, crea una nueva instancia de la página, ejecuta el código en ella y, a continuación, vuelve a representar la página en el explorador. Sin embargo, en efecto, la página no sabe que estaba trabajando con una versión anterior de sí misma. Todo lo que sabe es que obtuvo una solicitud que tenía algunos datos de formulario en ella.

Cada vez que solicite una página, ya sea por primera vez o al enviarla, obtendrá una nueva página. El servidor web no tiene memoria de la última solicitud. Tampoco ASP.NET y tampoco el explorador. La única conexión entre estas instancias independientes de la página es cualquier dato que transmita entre ellas. Si envía una página, por ejemplo, la nueva instancia de la página puede obtener los datos del formulario enviados por la instancia anterior. (Otra manera de pasar datos entre páginas es usar cookies).

Una manera formal de describir esta situación es decir que las páginas web no tienen estado. Los servidores web y las páginas y los elementos de la página no mantienen ninguna información sobre el estado anterior de una página. La web se diseñó de esta manera porque mantener el estado de las solicitudes individuales agotaría rápidamente los recursos de los servidores web, que a menudo controlan miles, quizás incluso cientos de miles, de solicitudes por segundo.

Por eso el cuadro de texto estaba vacío. Después de enviar la página, ASP.NET creó una nueva instancia de la página y ejecutó el código y el marcado. No había nada en ese código que indicase a ASP.NET que pusiera un valor en el cuadro de texto. Por lo tanto, ASP.NET no hizo nada y el cuadro de texto se representó sin un valor en él.

En realidad, hay una manera fácil de solucionar este problema. El género que especificó en el cuadro de texto está disponible en el código; se encuentra en Request.QueryString["searchGenre"].

Actualice el marcado del cuadro de texto para que el atributo value obtenga su valor de searchTerm, como en este ejemplo:

<input type="text" name="searchGenre" value="@Request.QueryString["searchGenre"]" />

En esta página, también podría haber establecido el atributo value en la variable searchTerm, ya que esa variable también contiene el género especificado. No obstante, el uso del objeto Request para establecer el atributo value como se muestra aquí es la manera estándar de realizar esta tarea. (Suponiendo incluso que quiera hacerlo, en algunas situaciones, es posible que quiera representar la página sin valores en los campos. Todo depende de lo que sucede en la aplicación).

Nota:

No se puede "recordar" el valor de un cuadro de texto que se usa para contraseñas. Sería un agujero de seguridad permitir que los usuarios rellenen un campo de contraseña mediante código.

Vuelva a ejecutar la página, escriba un género y haga clic en Search Genre. Esta vez, no solo verá los resultados de la búsqueda, sino que el cuadro de texto recuerda lo que escribió la última vez:

Page showing that the text box has 'remembered' the previous entry

Búsqueda por cualquier palabra del título

Ahora puede buscar cualquier género, pero es posible que también quiera buscar un título. Es difícil obtener un título exactamente justo al buscar, por lo que en su lugar puede buscar una palabra que aparezca en cualquier lugar dentro de un título. Para hacer esto en SQL, use el operador LIKE y una sintaxis como la siguiente:

SELECT * FROM Movies WHERE Title LIKE '%adventure%'

Este comando obtiene todas las películas cuyos títulos contienen la palabra "adventure". Cuando se usa el operador LIKE, se incluye el carácter comodín % como parte del término de búsqueda. La búsqueda LIKE 'adventure%' significa "que comienza por 'adventure'". (Técnicamente, significa "La cadena 'adventure' seguida de cualquier cosa"). Del mismo modo, el término de búsqueda LIKE '%adventure' significa "cualquier cosa seguida de la cadena 'adventure'", que es otra manera de decir "que termina con 'adventure'".

Por lo tanto, el término de búsqueda LIKE '%adventure%' significa "con 'adventure' en cualquier parte del título". (Técnicamente, "cualquier cosa en el título, seguido de 'adventure', seguido de cualquier cosa").

Dentro del elemento <form>, agregue el siguiente marcado justo debajo de la etiqueta de cierre </div> de la búsqueda de género (justo antes del elemento de cierre </form>):

<div>
  <label for="SearchTitle">Movie title contains the following:</label>
  <input type="text" name="searchTitle" value="@Request.QueryString["searchTitle"]" />
  <input type="Submit" value="Search Title" /><br/>
</div>

El código para controlar esta búsqueda es similar al código de la búsqueda de género, excepto que tiene que ensamblar la búsqueda LIKE. Dentro del bloque de código de la parte superior de la página, agregue este bloque if justo después del bloque if para la búsqueda de género:

if(!Request.QueryString["searchTitle"].IsEmpty() ) {
    selectCommand = "SELECT * FROM Movies WHERE Title LIKE @0";
    searchTerm = "%" + Request["searchTitle"] + "%";
}

Este código usa la misma lógica que vio anteriormente, salvo que la búsqueda usa un operador LIKE y el código coloca "%" antes y después del término de búsqueda.

Observe que ha sido fácil agregar otra búsqueda a la página. Todo lo que tenía que hacer era:

  • Crear un bloque if para ver si el cuadro de búsqueda correspondiente tenía un valor.
  • Establecer la variable selectCommand en una nueva instrucción SQL.
  • Establecer la variable searchTerm en el valor que se va a pasar a la consulta.

Este es el bloque de código completo, que contiene la nueva lógica para una búsqueda por título:

@{
    var db = Database.Open("WebPagesMovies") ;
    var selectCommand = "SELECT * FROM Movies";
    var searchTerm = "";

    if(!Request.QueryString["searchGenre"].IsEmpty() ) {
        selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
        searchTerm = Request.QueryString["searchGenre"];
    }

   if(!Request.QueryString["searchTitle"].IsEmpty() ) {
        selectCommand = "SELECT * FROM Movies WHERE Title LIKE @0";
        searchTerm = "%" + Request["searchTitle"] + "%";
    }

    var selectedData = db.Query(selectCommand, searchTerm);
    var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:8);
}

Este es un resumen de lo que hace este código:

  • Las variables searchTerm y selectCommand se inicializan en la parte superior. Va a establecer estas variables en el término de búsqueda adecuado (si existe) y el comando SQL adecuado en función de lo que hace el usuario en la página. La búsqueda predeterminada es el caso sencillo de obtener todas las películas de la base de datos.
  • En las pruebas de searchGenre y searchTitle, el código establece searchTerm en el valor que desea buscar. Esos bloques de código también establecen selectCommand en un comando SQL adecuado para esa búsqueda.
  • El método db.Query se invoca solo una vez, con cualquier comando SQL que haya en selectedCommand y cualquier valor de searchTerm. Si no hay ningún término de búsqueda (ningún género y ninguna palabra de título), el valor de searchTerm es una cadena vacía. Sin embargo, esto no importa, ya que en ese caso la consulta no requiere un parámetro.

Prueba de la característica búsqueda por título

Ahora, puede probar la página de búsqueda completada. Ejecute Movies.cshtml.

Escriba un género y haga clic en Search Genre. La cuadrícula muestra películas de ese género, como antes.

Escriba un género y haga clic en Search Title. La cuadrícula muestra las películas que tienen esa palabra en el título.

Movies page listing after searching for 'The' in the title

Deje ambos cuadros de texto en blanco y haga clic en cualquiera de los botones. La cuadrícula muestra todas las películas.

Combinación de las consultas

Es posible que haya observado que las búsquedas que puede realizar son exclusivas. No se puede buscar por título y género al mismo tiempo, incluso si ambos cuadros de búsqueda tienen valores en ellos. Por ejemplo, no puede buscar todas las películas de acción cuyo título contenga "Adventure". (Tal como está codificada la página ahora, si escribe valores para género y título, la búsqueda por título tiene prioridad). Para crear una búsqueda que combine las condiciones, tendría que crear una consulta SQL que tenga una sintaxis similar a la siguiente:

SELECT * FROM Movies WHERE Genre = @0 AND Title LIKE @1

Y tendría que ejecutar la consulta mediante una instrucción como la siguiente (aproximadamente hablando):

var selectedData = db.Query(selectCommand, searchGenre, searchTitle);

Crear una lógica que permita muchas permutaciones de criterios de búsqueda puede ser un poco complicado, como puede ver. Por lo tanto, nos detendremos aquí.

Próximamente

En el siguiente tutorial, creará una página que usa un formulario para permitir que los usuarios agreguen películas a la base de datos.

@{
    var db = Database.Open("WebPagesMovies") ;
    var selectCommand = "SELECT * FROM Movies";
    var searchTerm = "";

    if(!Request.QueryString["searchGenre"].IsEmpty() ) {
        selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
        searchTerm = Request.QueryString["searchGenre"];
    }

    if(!Request.QueryString["searchTitle"].IsEmpty() ) {
        selectCommand = "SELECT * FROM Movies WHERE Title LIKE @0";
        searchTerm = "%" + Request["searchTitle"] + "%";
    }

    var selectedData = db.Query(selectCommand, searchTerm);
    var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3);
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Movies</title>
    <style type="text/css">
      .grid { margin: 4px; border-collapse: collapse; width: 600px; }
      .grid th, .grid td { border: 1px solid #C0C0C0; padding: 5px; }
      .head { background-color: #E8E8E8; font-weight: bold; color: #FFF; }
      .alt { background-color: #E8E8E8; color: #000; }
    </style>
  </head>
  <body>
    <h1>Movies</h1>
      <form method="get">
        <div>
        <label for="searchGenre">Genre to look for:</label>
        <input type="text" name="searchGenre" value="@Request.QueryString["searchGenre"]" />
        <input type="Submit" value="Search Genre" /><br/>
        (Leave blank to list all movies.)<br/>
        </div>

        <div>
          <label for="SearchTitle">Movie title contains the following:</label>
          <input type="text" name="searchTitle" value="@Request.QueryString["searchTitle"]" />
          <input type="Submit" value="Search Title" /><br/>
        </div>
      </form>

    <div>
      @grid.GetHtml(
        tableStyle: "grid",
        headerStyle: "head",
        alternatingRowStyle: "alt",
        columns: grid.Columns(
          grid.Column("Title"),
          grid.Column("Genre"),
          grid.Column("Year")
        )
      )
    </div>
  </body>
</html>

Recursos adicionales