MVC 5 Bootstraps Vista Razor

Descargar como docx, pdf o txt
Descargar como docx, pdf o txt
Está en la página 1de 88

PROGRAMACIÓN DE APLICACIONES

DISTRIBUIDAS

Tutorial ASP.NET MVC 5


implementando Bootstrap y Vista
Razor

Paul, Víctor Leonardo


Legajo 30865
Introducción
Visual Studio es un IDE o entorno de desarrollo integrado. Al igual que usted utiliza
Microsoft Word para escribir documentos, vamos a usar un IDE para crear
aplicaciones.

Este tutorial le enseñará los conceptos básicos de la construcción de una aplicación


Web ASP.NET MVC 5 para Visual Studio 2013. Implementando un framework
denominado Bootstrap para crear las interfaces web con JavaScrip y CSS, un motor
de vistas llamado Razor el cual fue implementado desde la versión 3 de ASP.NET
MVC, está basado en plantillas de vistas y tiene una extensión de archivo .cshtml.
Además este mismo provee una manera elegante de crear una salida HTML con c#.

Razor minimiza el número de caracteres y tipeo necesario para escribir una plantilla de
vista y así permitir un trabajo rápido.

También puede hacer que la aplicación esté disponible a través de Internet mediante
el despliegue a un proveedor de hosting. Microsoft ofrece alojamiento web gratuito
para un máximo de 10 sitios web en una cuenta de prueba gratuita de Windows Azure
http://azure.microsoft.com/en-us/pricing/free-trial/?WT.mc_id=A443DD604

MVC (modelo-vista-controlador) es un patrón para el desarrollo de aplicaciones que


posee buena arquitectura, comprobable y fácil de mantener.
Las aplicaciones basadas en MVC contienen:

Modelos: Clases que representan los datos de la aplicación y que lógica de validación
usa para hacer cumplir las reglas de negocio para esos datos.
Vista: archivos de plantilla que la aplicación utiliza para generar dinámicamente
respuestas HTML.
Controlador: clases que manejan las solicitudes entrantes de navegación, recuperar
los datos del modelo, y luego especificar plantillas de vista que devuelven una
respuesta al navegador.

Primeros Pasos:

Comience instalando y ejecutando Visual Studio Express 2013 para Web del siguiente
enlace: http://www.visualstudio.com/downloads/download-visual-studio-vs#d-2013-
express

Una Vez instalado y ejecutado el Visual Studio podemos observar en la pantalla


principal distintas secciones como la barra de herramientas en la parte superior que
muestra múltiples opciones disponibles para usted. También hay un menú que ofrece
otra manera de realizar tareas en el IDE. (Por ejemplo, en lugar de seleccionar Nuevo
proyecto desde el inicio la página, puede utilizar el menú y seleccione Archivo > Nuevo
proyecto.)

1
Creación de su primera aplicación
La siguiente imagen muestra cómo crear un Nuevo Proyecto. Comience seleccionando
“Visual C #” a la izquierda, a continuación, “Web” y seleccione Aplicación “Web
ASP.NET”. Ingrese el nombre de su proyecto, en este caso utilizaremos "MvcMovie".
Seleccione donde desea guardar su proyecto, por defecto Visual Studio lo guarda en
su carpeta Projects. Y luego haga clic en Aceptar.

2
En el nuevo proyecto de ASP.NET de diálogo, haga clic en la plantilla MVC y luego
haga clic en Aceptar.

3
Visual Studio utiliza una plantilla predeterminada para el proyecto ASP.NET MVC que
acaba de crear, por lo que tiene una aplicación de trabajo en este momento sin hacer
nada! Este es un simple "Hola Mundo!" proyecto, y es un buen lugar para comenzar su
aplicación.

Presione F5 para ejecutar la aplicación web. Luego se abrira automáticamente un


navegador y muestra la página principal de la aplicación. A continuación podemos
observar que la barra de direcciones del navegador dice localhost: 52947 y no algo
como example.com. Esto se debe a localhost siempre apunta a su propio equipo local,
que en este caso se está ejecutando la aplicación que acaba de construir. En cuanto al
puerto (52947), se le asigna uno aleatorio.

4
A continuación podemos observar que en la parte superior derecho de la página
aparece el icono “IMAGEN”. Al hacer click en el mismo se desplazara el menú por
defecto de la plantilla el cual contiene campos como inicio, acerca de, registrar e inicio
de sesión

5
AGREGAR CONTROLADOR

A continuación aprenderemos como aplicar el patrón MVC.


Comenzaremos creando una clase Controlador como se muestra en la imagen
siguiente:

A continuación se abrirá una ventana para elegir el tipo de controlador que deseamos
agregar, en este caso seleccionamos la opción Controlador de MVC 5: En
blanco y hacemos click en agregar.
.

6
Ahora nos pedirá que ingresemos el nombre del controlador, en este caso
ingresaremos HolaMundo como modo de ejemplo y presionamos agregar.

En la siguiente imagen podemos observar que en el Explorador de Soluciones se


encuentra el controlador que acabamos de crear HolaMundo.cs y una carpeta Vistas
\ HolaMundo.

7
Abrimos el controlador que creamos y reemplazamos el código que contiene por el
siguiente:

8
Podemos observar la clase controlador HolaMundo que es la que creamos con
anterioridad, y dos método índice y Bienvenido, los cuales devuelven directamente
una cadena. Al Ejecutar la aplicación presionando F5 y agregando en la barra de
direcciones /HelloWorld observaremos el resultado del código ingresado.
Índice es el método por defecto que se llama en un controlador si no se especifica de
forma explícita.

La lógica de enrutamiento URL predeterminado utilizado por ASP.NET MVC utiliza el


siguiente formato para determinar qué código invocar:

9
/ [Controller] / [ActionName] / [Parameters]

Controlador: determina la clase del controlador a ejecutar

Nombre de la Acción: determina el método de acción de la clase a ejecutar.

Parámetros: especifica datos de rutas

LA siguiente imagen especifica cómo establecer el formato para la ruta


App_Start/RouteConfig.cs

A continuación ejecutamos la aplicación y en la barra de dirección ingresamos


http://localhost:52947/HelloWorld/Welcome como se muestra en la imagen.

Ahora modificaremos el método Welcome con el fin de agregar parámetros para el


controlador.
Cambiamos el método Welcome por el siguiente código:

10
Podemos observar que el parámetro numTime =1 toma el valor 1 por defecto en el
caso que no se le asigne un valor parámetro.

Reemplace el método Welcome por el siguiente código:

Ejecute la aplicación e introduzca la siguiente URL: http: // localhost:xxx /


HelloWorld/Welcome/3?name=Rick

En la imagen anterior se puede ver que el tercer segmento URL se correspondía con
el parámetro de ruta ID. El método Welcome contiene un parámetro (ID) que coincide
con la URL especificada en el método RegisterRoutes.

En las aplicaciones ASP.NET MVC es típico pasar parámetros como datos de ruta
(como lo muestra la imagen anterior) que como cadena de consultas. También se
puede agregar una ruta para los parámetros name y numtimes en
App_Start\RouteConfig.cs.
Agregue el siguiente código en RouteConfig.cs:

11
Presione F5 y en la barra de direcciones ingrese la siguiente ruta:
localhost:xxx/HelloWorld/Welcome/Scott/3

Como pudimos observar hasta aquí aplicamos los conceptos de Vista – Controlador
(VC) del modelo MVC, es decir la visión y el trabajo del controlador.

Agregar una vista


En esta sección vamos a modificar la clase HelloWorldController para utilizar archivos
de vista de plantilla para encapsular el proceso de generar respuestas HTML a un
cliente.

Como se vio en sección anterior el método Index devolvía una cadena con un mensaje
que se encontraba en la clase controlador. Ahora vamos a cambiar dicho Index de tal
forma que devuelva un objeto View ingresando el siguiente código.

Este método utiliza una plantilla de vista para generar una respuesta HTML al
navegador. Tanto el método controlador (también conocidos como métodos de
acción ), como este Index , generalmente devuelven un ActionResult (o una
clase derivada de ActionResult ) y no tipos primitivos como cadena.

12
Haga clic derecho en la carpeta HelloWorld de views y haga clic en Agregar y,
a continuación, haga clic MVC 5 Ver Página con (Diseño Razor).

En el Cuadro de Diálogo, ingrese Index, y luego haga clic en Aceptar. En la


Selección Página de Diseño, acepte el valor predeterminado _Layout.cshtml y
haga clic en Aceptar. En el cuadro de diálogo anterior, la carpeta Shared está
seleccionada en la izquierda del panel. Si tuvieras un archivo de diseño
personalizado en otra carpeta,
puede seleccionarlo.

13
Podemos observar que el archivo Index.cshtml fue cread HelloWorld.

14
Agregue el siguiente Código:

Haga clic derecho en el archivo Index.cshtml y seleccione Ver en el


explorador

15
Cambiar las vistas y el diseño de páginas

Para realizar esta acción vamos a Views/Shared/_Layout.cshtml en el


explorador de soluciones.

La Plantilla de diseño le permite especificar el formato contenedor HTML de su


sitio en un lugar y luego aplicarlo en varias páginas en su sitio. RenderBody es
un marcador de posición en el que todas las páginas específicas de vista que
cree se presentan, "envuelto" en la página de diseño. Por ejemplo, si
selecciona el enlace Acerca de, View\Home\About.cshtml vera que se
representa dentro del método RenderBody.

16
Para cambiar el contenido del título. Primero cambie el ActionLink en la plantilla
de diseño de "Application name" a "MVC Movie" y el controlador
de Inicio de Películas. El archivo de diseño completo se muestra a continuación:

A continuación ejecute la aplicación y observe como se cambio el titulo a MVC


Película. También logramos que este título se mantenga en todas las
pestañas.

El siguiente código Razor establece el diseño de la pagina

@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

17
Examine el archivo Views\_ViewStart.cshtml, que contiene exactamente el
mismo beneficio que Razor. El archivo Views\_ViewStart.cshtml define el
diseño común que todas las vistas utilizarán, por lo tanto, puede comentar o
eliminar el código del archivo Views\HelloWorld\Index.cshtm.

Puede utilizar la propiedad Layout para establecer una vista de diseño


diferente, o se establece en nulo por lo que no se utilizará ningún archivo de
diseño.

Ahora, vamos a cambiar el título de la vista Índice.

Abrir MvcMovie\views\HelloWorld\Index.cshtml. Hay dos lugares para hacer un


cambio: en primer lugar, el texto que aparece en el título del navegador, y luego
en el encabezado secundario (el elemento <h2>). Usted va a hacer de ellos un
poco diferente para que pueda ver que poco cambio el código en la aplicación.

@{
ViewBag.Title = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

18
Pasar datos del Controlador a la Vista

La Clase Controller se invoca en respuesta a una solicitud de URL entrante.


Una clase controlador es donde se escribe el código que maneja las solicitudes
entrantes de navegación, recuperan datos de una base de datos, y decide qué
tipo de respuesta devolver al navegador. Las plantillas vistas pueden utilizarse
desde un controlador para generar y dar formato a una respuesta HTML en el
navegador.

Los controladores son responsables de proporcionar cualquier dato u objetos


que se requiera para que una plantilla de vista entregue una respuesta al
navegador. Una buena práctica: Una plantilla de vista nunca debe realizar la
lógica de negocio o interactuar directamente con una base de datos. En
cambio, una plantilla de vista debe trabajar sólo con los datos que se
proporcionan a ella por el controlador. El mantenimiento de esta "separación de
intereses" ayuda a mantener el código limpio, comprobable y más fácil de
mantener.

Actualmente, el método de acción Welcome en la case HelloWorldController


toma los parámetros nombre y un numTimes y luego da salida a los valores
directamente en el navegador. En lugar de tener el controlador render como
una cadena, vamos a cambiar el controlador y utilizar una plantilla de vista en
su lugar. La plantilla de vista va a generar una respuesta dinámica, lo que
significa que usted necesita pasar apropiados bits de datos del controlador a la
vista, con el fin de generar una respuesta. Puede hacer esto haciendo que el
controlador ponga los datos dinámicos (parámetros) que la plantilla de vista
necesita en un objeto ViewBag para que la plantilla de vista pueda acceder.

Vuelva al archivo HelloWorldController.cs y cambie el método Welcome para


agregar un mensaje y el valor NumTimes al objeto ViewBag. ViewBag es un
objeto dinámico, lo que significa que puedes poner lo que quieras en el; el
objeto ViewBag tiene propiedades no definido hasta que coloque algo en su
interior. El modelo ASP.NET MVC mapea automáticamente los parámetros
name y numTimes de la cadena de consulta en la barra de direcciones a los
parámetros de su método. El archivo HelloWorldController.cs archivo se ve así:

using System . Web ;


using System . Web . Mvc ;

namespace MvcMovie . Controllers


{
public class HelloWorldController : Controller
{
public ActionResult Index ()
{
return View ();
}

19
public ActionResult Welcome ( string name , int numTimes =
1 )
{
ViewBag . Message = "Hello " + nombre ;
ViewBag . NumTimes = numTimes ;

devolver Ver ();


}
}
}

Ahora el objeto ViewBag contiene datos que se pasará a la vista de forma


automática. Después, usted necesita una vista de plantilla Welcome! En
el menú Build, seleccione Generar solución (o Ctrl + Shift + B) para
asegurarse de que el proyecto se compila. Haga clic derecho en la carpeta
Views\HelloWorld y haga clic en Agregar y, a continuación, haga clic en
Páginas de vistas de MVC 5 con Diseño (Razor).
En el Cuadro de Diálogo ingrese Bienvenido y haga clic en Aceptar . A
continuación acepte el valor predeterminado _Layout.cshtml y haga clic
en Aceptar.
En el archivo Welcome.cshtml vamos a crear un bucle que dice "Hola" tantas
veces como el usuario diga. El archivo Welcome.cshtml se muestra completo a
continuación.

Ejecute la aplicación y vaya a la siguiente URL:


http://localhost:xx/HelloWorld/Welcome?name=Scott&numtimes=4
Ahora, los datos se toman de la URL y se pasan al controlador usando
el modelo binder. El controlador empaqueta los datos en un objeto ViewBag y

20
pasa ese objeto a la vista. La vista a continuación, muestra al usuario los datos
como HTML.

En el ejemplo anterior, utilizamos un objeto ViewBag para pasar datos desde el


controlador a una vista. Al final del tutorial, vamos a utilizar un modelo de vista
para pasar datos de un controlador a una vista.

Agregar Modelo

En esta sección vamos a añadir en una base de datos algunas clases de la


gestión de las películas. Estas clases serán la parte del "modelo" de la
aplicación ASP.NET MVC.

Vamos a usar una tecnología de acceso a datos de .NET Framework conocido


como el Entity Framework para definir y trabajar con estas clases de modelo. El
Entity Framework (a menudo referido como EF) apoya un paradigma de
desarrollo llamado Code Firs (Primer Codigo). Code First le permite crear
objetos de modelo escribiendo clases simples. (Estos son también conocidos
como clases POCO, de " plain-old CLR."), Entonces usted puede tener la base
de datos creada sobre la marcha de sus clases, lo que permite un flujo de
trabajo de desarrollo muy limpio y rápido.

Agregar Clases al Modelo

En el Explorador de soluciones, haga clic derecho en la carpeta Models,


seleccione Agregar y, a continuación, seleccione la clase.

21
En el cuadro de dialogo ingrese el nombre “Movie”

En la clase creada agregue las siguientes cinco propiedades a la clase Movie:

22
Usaremos la clase Movie para representar películas en una base de
datos. Cada instancia de un objeto película corresponderá a una fila dentro de
una tabla de base de datos, y cada propiedad de la clase Movie se proyectará
en una columna en la tabla.

En el mismo archivo, agregue la siguiente clase MovieDBContext:

La clase MovieDBContext representa el contexto de la base de datos Movie de


Entity Framework, que se encarga de buscar, almacenar y actualizar Instancias
de la clase de Movie en una base de datos. El MovieDBContext deriva de la
clase DbContext proporcionada por el Entity Framework. Con el fin de hacer
referencia a DbContext y DbSet, es necesario agregar la librería using
System.Data.Entity; en la parte superior izquierda del archivo.

Con esto lo que hicimos es agregar un modelo (el M del MVC).

Creación de una cadena de conexión y trabajar con SQL Server


LocalDB

23
En esta sección vamos a añadir explícitamente una cadena de conexión en el
archivo Web.config de la aplicación.

La clase MovieDBContext que ha creado se encarga de conectar las bases de


datos y mapeo del objeto Movie a los registros de la base de datos. Una
pregunta que podría preguntar, sin embargo, es cómo especificar qué base de
datos va a conectar. En realidad no tiene que especificar qué base de datos
utilizar, Entity Framework utilizará por defecto LocalDB.

SQL Server Express LocalDB

LocalDB es una versión ligera del motor de base de datos SQL Server Express
que se inicia en la demanda y se ejecuta en modo de usuario. LocalDB ejecuta
en un modo especial de ejecución de SQL Server Express que le permite
trabajar con bases de datos como archivos .mdf. Normalmente, los archivos de
base de datos LocalDB se mantienen en la carpeta App_Data de un proyecto
web.
SQL Server Express no está recomendado para su uso en la producción de
aplicaciones web. LocalDB, en particular, no debe utilizarse para la producción
de una aplicación web, ya que no está diseñado para trabajar con IIS. Sin
embargo, una base de datos LocalDB se puede migrar cómodamente a SQL
Server o SQL Azure.
En Visual Studio 2013 (y en 2012), LocalDB se instala por defecto con Visual
Studio.
Por defecto, el Marco de la entidad busca una cadena de conexión con el
mismo nombre que la clase de contexto del objeto (MovieDBContext para este
proyecto).

Abra la raíz de la aplicación Web.config como se muestra a continuación. (No


el archivo Web.config de la carpeta Views).

24
Busque en el código del mismo el elemento <connectionStrings> :

Agregue la siguiente cadena de conexión al elemento <connectionStrings> en


el archivo Web.config.:
<add name="MovieDBContext"
connectionString="Data
Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Movies.mdf;Int
egrated Security=True"
providerName="System.Data.SqlClient"
/>

El siguiente ejemplo muestra una parte del archivo Web.config con la nueva
cadena de conexión añadido:
<connectionStrings>
<add name="DefaultConnection" connectionString="Data
Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-
MvcMovie-20130603030321.mdf;Initial Catalog=aspnet-MvcMovie-
20130603030321;Integrated Security=True"
providerName="System.Data.SqlClient" />
<add name="MovieDBContext" connectionString="Data
Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Movies.mdf;Int
egrated Security=True" providerName="System.Data.SqlClient"
/>

La primera cadena de conexión se llama DefaultConnection y se utiliza para la


base de datos de miembros para controlar quién puede acceder a la
aplicación.

25
La segunda cadena de conexión especifica una base de datos LocalDB
llamado Movie.mdf ubicado en la carpeta App_Data.

El nombre de la cadena de conexión debe coincidir con el nombre de la clase


DbContext.

público de clase MovieDBContext : DbContext


{
públicas DbSet < Película > Películas { consiguen ; set ;
}
}
}

Acceso a los datos de su modelo desde un controlador

En esta sección vamos a crear una nueva clase MoviesController y escribir un


código para recupera los datos del vídeo y mostrarlo en el navegador utilizando
una plantilla de vista.
Generar la aplicación antes de pasar al siguiente paso. Si no generar la
aplicación, usted obtendrá un error al agregar un controlador.
Para Generar la aplicación vaya a al menú Depurar/GenerarMvcMovie.
En el Explorador de soluciones, haga clic en la carpeta Controllers y luego
haga clic en Agregar y, a continuación Controlador.

En el cuadro de diálogo Agregar Scaffold, haga clic en Controlador de MVC 5


convistas que usa Entity Framework, y luego haga clic en Agregar.

26
Para el campo “nombre del controlador” ingrese MoviesController.
 Seleccione Movie (MvcMovie.Models) para la clase de modelo.
 Seleccione MovieDBContext (MvcMovie.Models) para la clase de
contexto de datos.

La siguiente imagen muestra el cuadro de diálogo completado.

27
Haga clic en Agregar. (Si se produce un error, es probable que no
construyeron la aplicación antes de comenzar la adición del controlador.) Visual
Studio crea los siguientes archivos y carpetas:
 Un archivo MoviesController.cs en la carpeta Controllers.
 Una carpeta Views\Movies. Con los siguientes archivos.
 Create.cshtml, Delete.cshtml, Details.cshtml, Edit.cshtml y Index.cshtml.
Visual Studio crea automáticamente el CRUD (crear, leer, actualizar y
eliminar) los métodos de acción y puntos de vista (la creación automática de
métodos y puntos de vista de acción CRUD se conoce como scaffolding).
Ahora tiene una aplicación web completamente funcional que le permite crear,
listar, editar y eliminar entradas de cine.
Ejecute la aplicación y haga clic en el enlace MVC Movie (o busque
el controlador Movie añadiendo /Movies a la dirección URL en la barra de
direcciones de su navegador). Debido a que la aplicación se basa en la ruta por
defecto (definido en el archivo App_Start\RouteConfig.cs), el navegador http://
localhost:xxxxx/Movies se redirecciona al método Índex del controlador
Movies. En otras palabras, el navegador de
petición http://localhost:xxxxx/Movies es efectivamente el mismo que el
navegador petición http://localhost:xxxxx/Movies/Índex. El resultado es una lista
vacía de películas, porque no se ha añadido ninguna todavía.

Crear una película

28
Seleccione el enlace Crear nuevo. Ingrese algunos detalles sobre una película
y luego haga clic en el Crear botón.

Al hacer clic en el Crear botón hace que el formulario se ha publicado en el


servidor, donde la información de la película se guarda en la base de datos y lo
redirecciona a la lista de las películas.

Evaluación del código generado

Abra el archivo Controllers/MoviesController.cs y examine el método índice.


public class MoviesController : Controller
{
private MovieDBContext db = new MovieDBContext();

29
// GET: /Movies/
public ActionResult Index()
{
return View(db.Movies.ToList());
}

Una petición al controlador Movies devuelve todas las entradas en la


tabla Movie y luego pasa los resultados al Index de views. La siguiente línea de
la clase MoviesController instancia un contexto de base de datos de la
película, como se describió anteriormente. Usted puede utilizar el contexto de
la base de la película para consultar, editar y borrar películas.
privado MovieDBContext db = nuevo MovieDBContext ();

Tipos de Modelos inflexibles y la palabra clave @Model

MVC también ofrece la posibilidad de pasar fuertemente objetos


mecanografiados a una plantilla de vista. Este tipo de enfoque inflexible
permite un mejor tiempo de compilación de su código y enriquecer
IntelliSense en el editor de Visual Studio. El mecanismo de scaffolding en Visual
Studio utiliza este enfoque con la clase MoviesController y las plantillas Views
cuando creó los métodos y puntos de vista.
En el archivo controladores\MoviesController.cs examine el método
generado details. El método Details se muestra a continuación.
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}

El parámetro id generalmente se pasa como datos de la ruta, por ejemplo http://


localhost:xxxx/Movies/Details/1 fijarán el controlador para el controlador de la

30
película, la acción de los details e id a 1. También podrían pasar en el id con
una cadena de consulta de la siguiente manera:
http://localhost:xxxx/Movies/Details?id=1
Si se encuentra una película, se pasa una instancia del modelo de la
película a la vista Detalles:
return View(movie);

Examine el contenido del archivo Views\Movies\Details.cshtml:

@model MvcMovie.Models.Movie

@{
ViewBag.Title = "Details";
}

<h2>Details</h2>

<div>
<h4>Movie</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Title)
</dt>
@*Markup omitted for clarity.*@
</dl>
</div>
<p>
@Html.ActionLink("Edit", "Edit", new { id = Model.ID }) |
@Html.ActionLink("Back to List", "Index")
</p>

Al incluir una declaración @Model en la parte superior del archivo de vista de


plantilla, puede especificar el tipo de objeto que la vista espera. Cuando
creó el controlador de la película, Visual Studio incluye automáticamente la
siguiente declaración @Model en la parte superior del archivo Details.cshtml:
@model MvcMovie.Models.Movie
@Model le permite acceder a la película que el controlador pasa a
la vista mediante el uso de un objeto de modelo que está inflexible. Por
ejemplo, en la pkantilla Details.cshtml, el código pasa cada campo de película a
los DisplayNameFor y DisplayFor HTML Helpers con el objeto de
modelo inflexible. Los métodos Crete y Edit y las plantillas de vista también
pasan un objeto de modelo de película.

31
Examine Index.cshtml de la plantilla Views y el método de Index en el
archivo MoviesController.cs. Observe cómo el código crea un objeto de
lista cuando se llama al metodo de ayuda Views en el método de la
acción Index.
public ActionResult Index()
{
return View(db.Movies.ToList());
}
Cuando creó el controlador de la película, Visual Studio incluye
automáticamente la siguiente declaración @modelo en la parte superior del
archivo Index.cshtml:
@model IEnumerable<MvcMovie.Models.Movie>
Esta directiva @Model le permite acceder a la lista de películas que el
controlador pasa a la vista mediante el uso de un objeto modelo que
está inflexible.
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<th>
@Html.DisplayFor(modelItem => item.Rating)
</th>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
@Html.ActionLink("Details", "Details", new { id=item.ID })
|
@Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
Dado que el objeto del modelo es de tipo fuerte (como un
IEnumerable <Movie> object), cada objeto de elemento en el circuito se escribe
como Movie.

32
Entre otras ventajas, esto significa que usted obtiene en tiempo de
compilación comprobación del código y la compatibilidad con
IntelliSense completo en el editor de código:

Trabajando con SQL Server LocalDB

Entity Framework Code First detectó que la cadena de conexión de base de


datos que se proporcionó señaló a una base de datos de películas que no
existía todavía, así Code First creó la base de datos de forma automática.
Usted puede comprobar que se ha creado mirando en la carpeta App_Data.
Si no ve el archivo Movies.mdf, haga clic en el botón Mostrar todos los
archivos en la barra de herramientas Explorador de soluciones, haga clic en
el botón Actualizar, a continuación, expanda la carpetaApp_Data.

33
Haga doble clic en Movies.mdf para abrir el Explorador de servidores, expanda
la carpeta Tablas para ver la tabla de Películas.

34
Haga clic con el la tabla Movie y seleccione Mostrar tabla de datos para ver los
datos que ha creado.

35
Haga clic en la tabla Movies y seleccione Abrir tabla de definición para
ver la estructura de la tabla que el Código de Entity Framework Code First ha
creado para usted.

Observe cómo el esquema de la tabla Movies asigna a la clase movie que creó
anteriormente.
Entity Framework Code First crea automáticamente este esquema para usted
basado en su clase Movies.
Cuando haya terminado, cierre la conexión haciendo clic
derecho MovieDBContext y seleccionando Cerrar conexión. (Si usted no cierra
la conexión, es posible que obtenga un error la próxima vez que se ejecuta el
proyecto).

36
Ahora tiene una base de datos y páginas para visualizar, editar, actualizar y
eliminar datos.

Examinar los métodos de edición y vista Edición

En esta sección, examinaremos los métodos de acción Editar generados y


puntos de vista para el controlador de Movie.
Pero primero tendrá un corto desvío para que la fecha de lanzamiento se vea
mejor.
Abra el archivo models\Movie.cs y agregue las líneas resaltadas que se
muestran a continuación:

using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;

namespace MvcMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }

37
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",
ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}

public class MovieDBContext : DbContext


{
public DbSet<Movie> Movies { get; set; }
}
}

También puede específicar la fecha de esta manera:


[Display(Name = "Release Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode =
true)]
public DateTime ReleaseDate { get; set; }

El atributo Display especifica lo que desea mostrar el nombre de un campo (en


este caso "Fecha de Lanzamiento" en lugar de"ReleaseDate"). El
atributo DataType especifica el tipo de los datos, en este caso se trata de una
fecha, por lo que la información de tiempo almacenada en el campo no se
muestra.
Se necesita el atributo DisplayFormat por un error en el navegador Chrome que
convierte formatos de fecha incorrecta.
Ejecutar la aplicación y busque el controlador Movies. Mantenga el puntero del
ratón sobre el enlace Editar para ver la URL que enlaza.

38
El enlace Editar fue generada por el método Html.ActionLink en la vista
Views\Movies\Index.cshtml
@Html.ActionLink("Edit", "Edit", new { id=item.ID })

El objeto Html es un ayudante que está expuesta utilizando una propiedad de la


clase base System.Web.Mvc.WebViewPage. El método ActionLink hace que
sea fácil de generar dinámicamente hipervínculos HTML que se enlazan
con métodos de acción en los controladores. El primer argumento del
método ActionLink es el texto del enlace arender (por
ejemplo, <a> Editar </a>).El segundo argumento es el nombre del método de
acción para invocar (En este caso, la acción de edición). El último
argumento es un objeto anónimo que genera los datos de la ruta (en este caso,
el ID de 4).
El enlace generado se muestra en la imagen anterior es
http: //localhost: 52947/Movies/Editar/3. La ruta por defecto (establecido

39
en App_Start\RouteConfig.cs) realiza el patrón de URL {controlador} / {acción} /
{id}.
Por lo tanto, ASP.NET traduce http://localhost:52947/Movies/Editar/3 en
una petición al método Edit acción del controlador Movies con el ID
de parámetro igual a 3. Examine el siguiente código del
archivo App_Start\RouteConfig.cs. El método MapRoute se utiliza para las
solicitudes HTTP ruta para el controlador y el método acción y suministrar el
parámetro opcional ID. El método MapRoute también es utilizado
por los HtmlHelper tales como ActionLink para generar URLs dado el
controlador, el método de acción y los datos de ruta.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index",
id = UrlParameter.Optional }
);
}

También puede pasar parámetros del método de acción utilizandouna cadena


de consulta. Por ejemplo, la dirección URL
http://localhost:52497/Movies/EditarID=3 también pasa el parámetro
ID del 3 al método Editar acción del controlador Movies.

Abra el controlador Movies. Los dos métodos de acción Editar se muestran a


continuación.
// GET: /Movies/Edit/5
public ActionResult Edit(int? id)
{

40
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}

// POST: /Movies/Edit/5
// To protect from overposting attacks, please enable the specific
properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult
Edit([Bind(Include="ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}

Observe el segundo método Edit acción va precedido por el atributoHttpPost.


Este atributo especifica que la sobrecarga del método de ediciónse puede
invocar sólo para peticiones POST. Se podría aplicar el atributo HttpGet con el
primer método de edición,pero eso no es necesario porque es el valor
predeterminado. (Nos referimos a los métodos de acción que se asignan de
forma implícita al atributo HttpGet como HTTPGet.) El atributoBind es
otro mecanismo de seguridad importante que mantiene a los hackers más de la
colocación de anuncios de datos a su modelo. Sólo debe incluir
propiedades en el enlace de atributos que desea cambiar. El
atributo ValidateAntiForgeryToken se utiliza para prevenir la falsificación de una
solicitud y se empareja con Html.AntiForgeryToken () en el archivo de vista de
edición (Views\Movies\Edit.cshtml). A continuación se muestra una parte:

@model MvcMovie.Models.Movie

@{

41
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.ID)

<div class="form-group">
@Html.LabelFor(model => model.Title, new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
</div>

@Html.AntiForgeryToken() genera una forma oculta anti-falsificación que debe


coincidir en el método Edit del controlador de Movies.

El método HttpGet Editar toma el parámetro ID película, busca la película


utilizando Entity Framework. Encuentre el método, y devuelve la película
seleccionada para la vista Editar. Si una película no se puede encontrar, se
devuelve HttpNotFound. Cuando el sistema de scaffolding crea la vista Editar,
examina la clase Movie y crea código para rendir <label> y <input> elementos
para cada propiedad de la clase. El siguiente ejemplo muestra la vista de
edición generada por el sistema de scaffolding de Visual Studio:

@model MvcMovie.Models.Movie

@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
@Html.ValidationSummary(true)

42
@Html.HiddenFor(model => model.ID)

<div class="form-group">
@Html.LabelFor(model => model.Title, new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ReleaseDate, new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.ReleaseDate)
@Html.ValidationMessageFor(model => model.ReleaseDate)
</div>
</div>
@*Genre and Price removed for brevity.*@
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-
default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}

Observe cómo la plantilla de vista tiene una declaración @Model


MvcMovie.Models.MovieModel en la parte superior del archivo - especifica que
la view espera que el modelo de la plantilla de vista sea del tipo Movies.

El código scaffolded utiliza varios métodos de ayuda para agilizar el formato


HTML. El ayudante Html.LabelFor muestra el nombre del campo ("Título",
"ReleaseDate", "Género", o "Precio"). El ayudante Html.EditorFor reproduce una
etiqueta HTML <input>. El ayudante Html.ValidationMessageFor muestra los
mensajes de validación asociados con esa propiedad.
Ejecute la aplicación y agregue en la URL /Movies. Haga click en el enladie
Editar. En el navegador, haga click derecho y selecciones “ver el código

43
fuente de la página”. El código HTML para el elemento de formulario se muestra
a continuación.

<form action="/movies/Edit/4" method="post">


<input name="__RequestVerificationToken" type="hidden"
value="UxY6bkQyJCXO3Kn5AXg-6TXxOj6yVBi9tghHaQ5Lq_qwKvcojNXEEfcbn-
FGh_0vuw4tS_BRk7QQQHlJp8AP4_X4orVNoQnp2cd8kXhykS01" /> <fieldset
class="form-horizontal">
<legend>Movie</legend>

<input data-val="true" data-val-number="The field ID must be a


number." data-val-required="The ID field is required." id="ID"
name="ID" type="hidden" value="4" />

<div class="control-group">
<label class="control-label" for="Title">Title</label>
<div class="controls">
<input class="text-box single-line" id="Title"
name="Title" type="text" value="GhostBusters" />
<span class="field-validation-valid help-inline" data-
valmsg-for="Title" data-valmsg-replace="true"></span>
</div>
</div>

<div class="control-group">
<label class="control-label" for="ReleaseDate">Release
Date</label>
<div class="controls">
<input class="text-box single-line" data-val="true" data-
val-date="The field Release Date must be a date." data-val-
required="The Release Date field is required." id="ReleaseDate"
name="ReleaseDate" type="date" value="1/1/1984" />
<span class="field-validation-valid help-inline" data-
valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
</div>
</div>

<div class="control-group">
<label class="control-label" for="Genre">Genre</label>
<div class="controls">
<input class="text-box single-line" id="Genre"
name="Genre" type="text" value="Comedy" />
<span class="field-validation-valid help-inline" data-
valmsg-for="Genre" data-valmsg-replace="true"></span>
</div>

44
</div>

<div class="control-group">
<label class="control-label" for="Price">Price</label>
<div class="controls">
<input class="text-box single-line" data-val="true" data-
val-number="The field Price must be a number." data-val-required="The
Price field is required." id="Price" name="Price" type="text"
value="7.99" />
<span class="field-validation-valid help-inline" data-
valmsg-for="Price" data-valmsg-replace="true"></span>
</div>
</div>

<div class="form-actions no-color">


<input type="submit" value="Save" class="btn" />
</div>
</fieldset>
</form>

Los elementos <input> se encuentran en una etiqueta <form>elemento


cuyo atributo action establece publicar en la URL /Movies/Editar. Los datos del
formulario se publicarán en el servidor cuando se hace clic en el botón Guardar.
La segunda línea muestra el token XSRF oculto generado por la
llamada @Html.AntiForgeryToken().

El procesamiento de la Petición POST

El siguiente listado muestra la versión HttpPost del método Edit acción.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult
Edit([Bind(Include="ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);

45
}

El atributo ValidateAntiForgeryToken valida el token XSRF generado por la


llamada @Html.AntiForgeryToken() en la vista.

El modelo ASP.NET MVC toma los valores a un formulario y crea un objeto


Movie que pasa como parámetro la película. El
método ModelState.IsValid verifica que los datos presentados en la forma se
pueden utilizar para modificar (editar o actualizar) un objeto Movie. Si los datos
son válidos, los datos de Movie se guarda en la colección de Movies de la db (instancia
MovieDBContext). Los nuevos datos de la película se guardan en la base de
datos llamando al método SaveChanges de MovieDBContext. Después de
guardar los datos, el código redirige al usuario al método de acción Index de la
clase MoviesController, que muestra la colección de
películas, incluyendo los cambios que acaba de hacer.

Tan pronto como la validación del lado del cliente determina que valores de un
campo no son válidos, se muestra un mensaje de error. Si
deshabilita JavaScript, usted no tendrá validación del lado del cliente, pero el
servidor detectará que los valores publicados no son válidos, y en los valores
del formulario se vuelven a mostrar los mensajes de error.

El ayudante Html.ValidationMessageFor en las plantilla de vista Edit.cshtml se


encarga de mostrar los mensajes de error correspondientes.

Todos los métodos HTTPGet siguen un patrón similar. Consiguen un objeto de


película (o lista de objetos, en el caso del index), y pasan el modelo a la vista.

46
El método Create pasa un objeto de película vacío a la vista Crear.
Los métodos crear, editar, borrar o modificar los datos lo hacen en los métodos
de sobrecarga HttpPost. La Modificación de datos en un método HTTP GET
es un riesgo de seguridad, tal como se describe en la entrada
de blog MVCASP.NET Tip # 46 - No utilice enlace Delete porque crean agujeros
de seguridad. La Modificación de datos en un método GET HTTP también
viola las mejores prácticas y el patrón de arquitectura REST, que especifica
que las peticiones GET no deberían cambiar el estado de su solicitud. En otras
palabras, la realización de una operación GET debe ser una operación
segura que no tiene efectos secundarios y no modifica sus datos persistido.

Si está utilizando una computadora de EE.UU.-Inglés, puede saltarse esta sección


y vaya a la siguiente tutorial.

1. Desde el Herramientas menú, haga clic en Administrador de


paquetes NuGet y, a continuación, haga clic enAdministrar paquetes
NuGet para solución.

2. En el panel izquierdo, seleccione En línea. (Ver la imagen de abajo.)


3. En el cuadro búsqueda de paquetes Instalado introduzca Globalize.
4. Haga clic en Instalar. Los archivos Scripts\jquery.globalize\globalize.js se
añadirán a su proyecto. La carpeta Scripts\jquery.globalize\culture\
contendrán muchos archivos JavaScript culture. Tenga en cuenta, puede
tomar cinco minutos para instalar este paquete.

47
El siguiente código muestra las modificaciones al archivo
Views\Movies\Edit.cshtml:

48
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")

<script src="~/Scripts/globalize/globalize.js"></script>
<script
src="~/Scripts/globalize/cultures/globalize.culture.@(System.Threading
.Thread.CurrentThread.CurrentCulture.Name).js"></script>
<script>
$.validator.methods.number = function (value, element) {
return this.optional(element) ||
!isNaN(Globalize.parseFloat(value));
}
$(document).ready(function () {

Globalize.culture('@(System.Threading.Thread.CurrentThread.CurrentCult
ure.Name)');
});
</script>
<script>
jQuery.extend(jQuery.validator.methods, {
range: function (value, element, param) {
//Use the Globalization plugin to parse the value
var val = Globalize.parseFloat(value);
return this.optional(element) || (
val >= param[0] && val <= param[1]);
}
});
$.validator.methods.date = function (value, element) {
return this.optional(element) ||
Globalize.parseDate(value) ||
Globalize.parseDate(value, "yyyy-MM-dd");
}
</script>
}

Para evitar la repetición de este código en todas las vistas de edición,


puede moverlo al archivo de diseño.

Como solución temporal, si usted no puede conseguir trabajo de validación en


su localidad, puede forzar el equipo para utilizar ingles estadounidenses o
puede desactivar JavaScript en su navegador. Para forzar el equipo para
utilizar EE.UU. Inglés, usted puede agregar el elemento de la globalización en
el archivo raíz del proyecto web.config. El siguiente código muestra el elemento
de la globalización de la cultura establecida en Estados Unidos Inglés.

49
<system.web>
<globalization culture ="en-US" />
<!--elements removed for clarity-->
</system.web>

Search (Búsqueda)

Adición de un método Search y de Views Search

En esta sección, agregará capacidad de búsqueda para el método de


acción Index que le permite buscar películas por género o nombre.

Actualización del formulario de Index

Comience por la actualización del método de acción Index de la clase


MoviesController existente. Aquí se muestra 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 la consulta followingLINQ para


seleccionar las películas:

var movies = from m in db.Movies


select m;

La consulta se define en este punto, pero aún no se ha ejecutado en contra de


la base de datos.

50
Si el parámetro searchstring contiene una cadena, la consulta de peliculas se
modifica para filtrar en el valor de la cadena de búsqueda, usando el siguiente
código:
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}

El código s => s.title anterior es una expresión lambda. Lambdas se utilizan en


métodos basados en consultas LINQ como argumentos a métodos
estándar operador de consulta tales como el método en el que se utiliza en el
código anterior. Las consultas LINQ no se ejecutan cuando se definen o cuando
se modifican llamando a un método como WHERE o OrderBy. En su lugar, la
ejecución de consultas se difiere, lo que significa que la evaluación de una
expresión se retrasa hasta su valor realizado en realidad repiten a lo largo o se
llama al método ToList. En la muestra de búsqueda, la consulta se ejecuta en la
vista Index.cshtml. Nota: El método Contains ejecuta en la base de datos, no
el código c # anteriormente. La base de datos, Contiene mapas a SQL LIKE,
que es sensible a mayúsculas.

Ahora usted puede actualizar la vista de índice que mostrará el formulario al


usuario.
Ejecute la aplicación y vaya a /Movies/Index. Anexar una cadena de
consulta como ?searchString=ghost para el URL. Se muestran
las películas filtradas.

Si cambiar la firma del método Index debe tener un parámetro llamado id, el
parámetro id coincidirá con el {id} marcador de posición para las rutas por
defecto establecidos en el archivo App_Start\RouteConfig.cs.

{ controller } / { acción } / { ID }

El método Index original se parece a esto:

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

51
}

El método Index modificado se vería de la siguiente manera:

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 titulo de búsqueda como datos de la ruta (un


segmento 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 quieren buscar una película. Así que ahora vamos a
añadir la interfaz de usuario para ayudarles a filtrar películas. Si ha cambiado
la firma del método Index para probar cómo pasar el parámetro ID como
ruta determinada, cambie de nuevo para que su método de 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 ("Crear nuevo", "Crear"), añadir la forma de marcas que se
destacan a continuación:

@model IEnumerable<MvcMovie.Models.Movie>

52
@{
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 ayudante Html. BeginForm crea una apertura <form>.El


ayudante Html.BeginForm causa la forma de enviar a sí mismo cuando el usuario
envía el formulario haciendo clic en el botón Filtro.
Visual Studio 2013 tiene una buena mejora en la visualización y edición de Ver
archivos. Al ejecutar la aplicación con una vista abierta archivo, Visual
Studio2013 invoca el método de acción del controlador correcto para mostrar la vista.

53
Con el archivo Index de View abierto en Visual Studio (como se muestra en la imagen
de arriba), toque Ctr F5 o F5 para ejecutar la aplicación y luego intentar la búsqueda
de una película.
No hay sobrecarga HttpPost del método Index. Usted no lo necesita, porque el
método no cambia el estado de la aplicación, el filtrado de datos.
Se podría añadir el siguiente método HttpPost Index. En ese caso, el invocador acción
podría coincidir con el método HttpPost Index, y el
método HttpPost Índice correría 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, incluso si se agrega esta versión del metodo HttpPostIndex, hay
una limitación en la forma en que todo esto ha sido implementado. Imagine que
usted desea marcar una búsqueda particular o desea enviar un enlace a tus
amigos que pueden hacer clic con el fin de 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

54
cadena de búsqueda se envía al servidor como un valor de campo de formulario.
Esto significa que no puede capturar esa información de búsqueda demarcador
o enviar a los amigos en una URL.
La solución es utilizar una sobrecarga de BeginForm que especifica que la petición
POST debe añadir la información de búsqueda de la URL y que debe ser enviado
a la HttpGet versión del método Index. Reemplace el método BeginForm sin
parámetros existente con el siguiente código:

@using (Html.BeginForm("Index","Movies",FormMethod.Get))

Ahora, cuando usted envía una búsqueda, la URL contiene una cadena de consulta
de búsqueda. La búsqueda también irá al método de acción HttpGet Index, incluso si
usted tiene un método HttpPost Index.

Agregar búsqueda por género

Si ha añadido la versión HttpPost del método Index, borrarlos ahora.


A continuación, vamos a añadir una función para permitir a los usuarios buscar
películas por género. Reemplace el método Index con el siguiente 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;

55
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 nombrado movieGenre.
Las primeras líneas de código crean un objeto de lista para celebrar géneros
cinematográficos, desde la base de datos.
El código siguiente es una consulta LINQ que recupera todos los géneros, desde la
base de datos.
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;

El código utiliza el método AddRange de la colección de lista genérica para añadir


todos los géneros distintos a la lista. (Sin el modificador Distinto, se
añadirían géneros duplicados - por ejemplo, se añadiría la comedia en dos ocasiones
en nuestra muestra). El código a continuación, almacena la lista de géneros en el
objeto ViewBag.movieGenre. Almacenamiento de datos de categoría (de un género de
películas) como un objeto SelectList en un ViewBag, a continuación, acceder a
los datos de categoría en un cuadro de lista desplegable es un enfoque típico
para aplicaciones MVC.

El siguiente código muestra cómo comprobar el parámetro movieGenre. Si no está


vacío, el código restringe aún más las películas de consulta para
limitar las películas seleccionadas para el género especificado.

if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);

56
}

Como se dijo anteriormente, la consulta no se ejecuta en la base de datos hasta que


la lista de películas se repite a lo largo (que ocurre en la vista, después del
método indexAction devoluciones).

Agregar marcado del Index Views para Buscar por Género

Añadir un Html.DropDownList al archivo Views\Movies\Index.cshtml, antes del


TextBox.

@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 siguiente código:
@Html.DropDownList("movieGenre", "All")

El parámetro "movieGenre" proporciona la clave para el ayudante DropDownList para


encontrar un IEnumerable <SelectListItem> en el ViewBag. El ViewBag fue
poblada 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;

57
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 el elemento de la lista para ser preseleccionado. Si


hubiéramos usado el siguiente código:
@Html.DropDownList("movieGenre", "Comedy")

Y tuviéramos una película con un género "Comedia" en nuestra base de


datos, "Comedia" sería preseleccionado en la lista desplegable. Porque no
tenemos un género de la película "All", no hay "All" en SelectList, así que cuando
nos fijamos de nuevo sin hacer un selection, el valor de cadena de
consulta movieGenre está vacía.

Ejecute la aplicación y vaya a /Movies/Index. Intente una búsqueda por


género, por nombre de la película, y por ambos criterios.

58
En esta sección se ha creado un método de acción de búsqueda y la
vista que permiten a los usuarios buscar por título de la película y el género.

Adición de un nuevo campo

En esta sección vamos a usar Entity Framework Code First migraciones para
migrar algunos cambios en las clases del modelo de manera que se aplique el cambio
en la base de datos.
Por defecto, se utiliza Entity Framework Code First para crear automáticamente una
base de datos, como lo hizo anteriormente en este tutorial, Code First agrega una
tabla a la base de datos para ayudar a rastrear si el esquema de la base de datos está
en sintonía con el modelo de clases que fue generada. Si no están en sincronía, Entity
Framework genera un error. Esto hace que sea más fácil de localizar problemas en el
tiempo de desarrollo que de otro modo sólo podría encontrar (por errores oscuros) en
tiempo de ejecución.

Configuración Code First Migrations para cambios en el modelo

Vaya al Explorador de soluciones. Haga clic derecho sobre el archivo y seleccione


Eliminar Movies.mdf para eliminar la base de datos de películas. Si no ve el
archivo Movies.mdf, haga clic en el icono de Mostrar todos los archivos

59
.

Genere la aplicación para asegurarse de que no hay errores.


Desde el menú Herramientas, haga clic en Administrador de paquetes NuGet y
luego consola del Administrador de paquetes.

En la ventana de la consola del Administrador de paquetes en el PM> teclee


Enable-Migraciones -ContextTypeName MvcMovie.Models.MovieDBContext

60
El comando Enable-Migraciones (ver imagen superior) crea un
archivo Configuration.cs en una nueva carpeta de Migraciones.

Visual Studio abre el archivo Configuration.cs. Reemplace el método Seed en el


archivo Configuration.cs con el siguiente código:
protected override void Seed(MvcMovie.Models.MovieDBContext context)
{
context.Movies.AddOrUpdate( i => i.Title,
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-1-11"),
Genre = "Romantic Comedy",
Price = 7.99M
},

61
new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},

new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},

new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);

Haga clic derecho sobre la línea roja ondulada bajo Movie y selectResolve y
luego haga clic en usingMvcMovie.Models;

62
Si lo hace, añade la siguiente instrucción using:
using MvcMovie.Models;

Presione CTRL-SHIFT-B para construir el proyecto. (Los siguientes pasos se


producirá un error si no construir en este punto.)
El siguiente paso es crear una clase DbMigration para la migración inicial. Esta
migración crea una nueva base de datos, es por eso que ha borrado el
archivo movie.mdf en un paso anterior.
En la ventana de la consola del Administrador de paquetes, ingrese el comando add-
migration Initial para crear la migración inicial. El nombre "initial" es arbitrario y se
utiliza para nombrar el archivo de migración creado.

Code First Migration crea otro archivo de clase en la carpeta de Migraciones (con el
nombre {DateStamp} _Initial.cs), y esta clase contiene código que crea el esquema
de base de datos. El nombre del archivo de migración está pre-fijada con una marca
de tiempo para ayudar con el pedido. Examine el archivo {DateStamp} _Initial.cs, que
contiene las instrucciones para crear la tabla Películas para la película DB. Al
actualizar la base de datos en las instrucciones a continuación, este
archivo {DateStamp} _Initial.cs se ejecutará y creara el esquema de base de datos.
A continuación, el método de Seed correrá a poblar la DB con los datos de prueba.
En la consola del Administrador de paquetes, tipee el comando update-database para crear la
base de datos y ejecutar el método Seed

63
Si recibe un error que indica una tabla ya existe y no se puede crear, es
probablemente porque se le terminó la aplicación después de que ha eliminado la
base de datos y antes de ejecutar update-database. En ese caso, elimine el
archivo Movies.mdf de nuevo y vuelva a intentar el comando update-database. Si
continúa recibiendo un error, elimine la carpeta migraciones y contenido a
continuación, iniciar con las instrucciones en la parte superior de esta
página (es borrar el archivo Movies.mdf luego proceder a Enable-Migraciones).

Ejecute la aplicación y vaya a la URL /Movies. Se muestran los datos del Seed.

Adición de una Clasificación de la Propiedad al Modelo Pelicula

Comience por agregar una nueva propiedad de Calificación a la clase Movie existente.
Abra el archivo models\Movie.cs y añada la propiedad Rating como éste:
public string Rating { get; set; }
La clase completa de Movie ahora se ve como el siguiente código:
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }

[Display(Name = "Release Date")]

64
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",
ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
public string Rating { get; set; }
}

Generar la aplicación (Ctrl + Shift + B).


Debido a que ha añadido un nuevo campo a la clase de Movie, también es
necesario actualizar la lista blanca de la unión por lo que esta nueva propiedad será
incluida. Actualice el atributo bind para Crear y el método de acción de edición para
incluir la propiedad Rating:
[Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")]

También es necesario actualizar las plantillas de vista con el fin de visualizar, crear y
editar la nueva propiedad Rating en la vista del navegador.
Abra el archivo \Viewa\Movies\Index.cshtml y añada un <th>Rating</ th> encabezado
de columna justo después de la columna Precio. A continuación, agregue un elemento
columna <td> cerca del final de la plantilla para tener el valor@item.Rating. A
continuación se muestra la plantilla de vista Index.cshtml actualizada:
@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">
<tr>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.ReleaseDate)

65
</th>
<th>
@Html.DisplayNameFor(model => model.Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Price)
</th>
<th>
@Html.DisplayNameFor(model => model.Rating)
</th>

<th></th>
</tr>

@foreach (var item in Model) {


<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Rating)
</td>

<td>
@Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
@Html.ActionLink("Details", "Details", new { id=item.ID })
|
@Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}

</table>

66
A continuación, abra la carpeta \Views\Movies\Create.cshtml y agregue el
campo Clasificación con el siguiente marcado highlighed. Esto hace que un cuadro de
texto pueda especificar una clasificación cuando se crea una nueva película.

<div class="form-group">
@Html.LabelFor(model => model.Price, new { @class = "control-
label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Price)
@Html.ValidationMessageFor(model => model.Price)
</div>
</div>

<div class="form-group">
@Html.LabelFor(model => model.Rating, new { @class = "control-
label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Rating)
@Html.ValidationMessageFor(model => model.Rating)
</div>
</div>

<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default"
/>
</div>
</div>
</div>
}

<div>
@Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}

Ahora usted ha informado el código de la aplicación para apoyar la nueva


propiedad de Calificación.
Ejecute la aplicación y vaya a la URL /Movies. Al hacer esto, sin embargo, verá uno de
los siguientes errores:

67
El modelo de respaldo al contexto 'MovieDBContext' ha cambiado desde que se
creó la base de datos. Considere el uso de Code First Migrations de actualizar la base
de datos (http://go.microsoft.com/fwlink/?LinkId=238269).

68
Estás viendo este error porque la clase del modelo Movie actualizadoen la
aplicación es ahora diferente que el esquema de la tabla de la película de la base de
datos existente. (No hay columna de Clasificación en la tabla de base de datos.).

Actualizar el método de Seed de modo que proporcione un valor para la nueva


columna. Abrir el archivo Migrations\Configuration.cs y agregue un campo Rating
a cada objeto de película.
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-1-11"),
Genre = "Romantic Comedy",
Rating = "PG",
Price = 7.99M
},

Construir la solución, y luego abra la ventana de la consola del Administrador de


paquetes e introduzca el siguiente comando: add-migration Rating
El comando add-migración cuenta la infraestructura de migración para examinar el
modelo actual de la película con el esquema MovieDB actual y crear el código
necesario para migrar la base de datos para el nuevo modelo. El nombre Rating
es arbitrario y se utiliza para nombrar el archivo de migración. Es útil usar un nombre
significativo para el paso de migración.

Cuando este comando finalice, Visual Studio abre el archivo de clase que define la
nueva clase DbMIgration derivados, y en el método de arriba se puede ver el código
que crea la nueva columna.
public partial class AddRatingMig : DbMigration
{
public override void Up()
{
AddColumn("dbo.Movies", "Rating", c => c.String());
}

public override void Down()


{
DropColumn("dbo.Movies", "Rating");
}
}

Construir la solución, y luego ingresar update-database del sistema en la consola


del Administrador de paquetes ventana.
La siguiente imagen muestra el resultado en la ventana de la consola del
Administrador de paquetes (La fecha del sello prepending Rating será diferente.)

69
Vuelva a ejecutar la aplicación y vaya a la URL /Movies

Haga clic en el enlace crear nuevo para agregar una nueva película. Tenga en cuenta
que usted puede añadir una calificación.

70
Haga click en Crear. La nueva película, incluida la clasificación, ahora aparece en las
películas del anuncio:

Ahora que el proyecto es el uso de las migraciones, usted no tendrá que dejar la base
de datos cuando se agrega un nuevo campo o actualizar de otra manera el esquema.

También debe agregar el campo Rating a la edición, Detalles Borrar plantillas de vista.
Puede introducir el comando "update-database" en la ventana de la consola del
Administrador de paquetes nuevo y sin código demigración tendría que
ejecutar, porque el esquema coincide con el modelo. Sin embargo, ejecutar "update-
database" se ejecutará el método de Seed de nuevo, y si ha cambiado alguno de los
datos del Seed, los cambios se perderán porque los datos del método de
Seed upserts.

En esta sección usted vio cómo se pueden modificar los objetos del
modelo y mantener la base de datos en sincronía con los cambios. También ha
aprendido una manera de rellenar una base de datos recién creada con datos de la
muestra para que pueda probar escenarios.

71
Adición de Validación

En esta sección vamos a añadir lógica de validación para el modelo Movies, y se


asegurará de que las reglas de validación se aplican cada vez que un usuario
intenta crear o editar una película utilizando la aplicación.

Mantener Cosas DRY

Uno de los principios fundamentales de diseño de ASP.NET MVC es DRY ("Do


not Repeat Yourself"). ASP.NET MVC le estimula para especificar la funcionalidad o
comportamiento sólo una vez, y luego tienen que reflejarse en todas partes en una
aplicación. Esto reduce la cantidad de código que necesita para escribir y hace que
el código que escribes sea menos propenso a errores y fácil de mantener.

El apoyo proporcionado por la validación ASP.NET MVC y Entity Framework Code


Firstes son un gran ejemplo del principio DRY en acción. Puede especificar de forma
declarativa reglas de validación en un solo lugar (en la clase del modelo) y las
normas se aplican en todas partes en la aplicación.

Echemos un vistazo a cómo usted puede tomar ventaja de este soporte de validación en la
aplicación de la película.

Adición de reglas de validación para el modelo Movie

Vamos a empezar añadiendo un poco de lógica de validación a la clase Movie.

Abra el archivo Movie.cs. Observe el espacio de


nombresSystem.ComponentModel.DataAnnotations no contiene System.Web.
DataAnnotations proporciona un conjunto integrado de validación de atributos que se
pueden aplicar de forma declarativa de cualquier clase o propiedad (También
contiene atributos de formato como el tipo de datos que ayudan con el formato y que
no ofrecen ningún tipo de validación.).
Ahora actualizar la clase de Movie para tomar ventaja de la incorporada
en Obligatorio, StringLength, RegularExpression y atributos de validación de rango.
Vuelva a colocar la clase de película con lo siguiente:
public class Movie
{
public int ID { get; set; }

[StringLength(60, MinimumLength = 3)]


public string Title { get; set; }

72
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",
ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
[Required]
[StringLength(30)]
public string Genre { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
[StringLength(5)]
public string Rating { get; set; }
}

El atributo StringLength establece la longitud máxima de la cadena, y establece esta


limitación en la base de datos, por lo tanto, el esquema de base de datos va a
cambiar. Haga clic en la tabla Movies en el Explorador de servidores y haga clic en
Abrir tabla de definición

73
:

En la imagen superior, se puede ver todos los campos de cadena se establecen en


NVARCHAR (MAX). Vamos a utilizar las migraciones para actualizar el esquema.
Construir la solución, y luego abrir la consola del Administrador de paquetes ventana
e introduzca los siguientes comandos:
add-migration DataAnnotations
update-database

Cuando estos comandos terminen, Visual Studio abre el archivo de clase que define la
nueva DbMIgration clase derivada con el nombre especificado (DataAnnotations), y en
el método de arriba se puede ver el código que actualiza las restricciones de
esquema:
public override void Up()
{
AlterColumn("dbo.Movies", "Title", c => c.String(maxLength: 60));
AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false,
maxLength: 30));
AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5));
}

El campo de Género ya no son anulable (es decir, se debe introducir un valor). El


campo Rating tiene una longitud máxima de 5 y Title tiene una longitud máxima de 60.

74
La longitud mínima de 3 en el Título y el rango de precio no creó los cambios de
esquema

Examinar el esquema de la película:

Los campos de cadena muestran los nuevos límites de longitud y Género ya no está
marcada como anulable.

Los atributos de validación especifican el comportamiento que desea aplicar a las del
modelo que se aplican. Los atributos Required y MinimumLength indican que
una propiedad debe tener un valor; pero nada impide que un usuario entrar en el
espacio blanco para satisfacer esta validación. El atributo RegularExpression se utiliza
para limitar lo que los personajes se pueden introducir. En el código anterior, Género y
clasificación deben utilizar sólo letras (espacios en blanco, números y caracteres
especiales no están permitidos). El atributo Range limita a un valor dentro de un rango
especificado. El atributo StringLength le permite ajustar la longitud máxima de una
propiedad de cadena y, opcionalmente, su longitud mínima. Los tipos de
valor (como decimal, int, float, DateTime) son inherentemente necesarios y no
necesitan el atributo Required.

Code First asegura que las reglas de validación que especifique en una clase del
modelo se aplican antes de que la aplicación guarde los cambios en la base de datos.
Por ejemplo, el código de
abajo arrojará una excepciónDbEntityValidationException cuando se llama al método
SaveChanges, debido a que varios valores de propiedad de película requerida faltan:

MovieDBContext db = new MovieDBContext();


Movie movie = new Movie();
movie.Title = "Gone with the Wind";
db.Movies.Add(movie);
db.SaveChanges(); // <= Will throw server side validation exception

El código anterior arroja la siguiente excepción:

75
Error de validación de una o más entidades.Ver propiedades. 'EntityValidationErrors' para mas
detalles.

Tener reglas de validación forzadas automáticamente por el .NET Framework ayuda a


hacer su aplicación más robusta. También asegura que no se puede olvidar de
validar algo y sin querer dejar malos datos en la base de datos.

Error de validación de IU en ASP.NET MVC

Ejecute la aplicación y vaya a la URL /Movies.

Haga clic en el enlace crear nuevo para agregar una nueva película. Rellene
el formulario con algunos valores no válidos. Tan pronto como la validación del lado
del cliente jQuery detecta el error, se muestra un mensaje de error.

Observe cómo la forma se ha utilizado de forma automática un color de


borde rojo para destacar los cuadros de texto que contienen datos no válidos y
ha emitido un mensaje de error de validación apropiad oal lado de cada uno.
Los errores se aplican tanto del lado del cliente (usando JavaScript y jQuery) como del
lado del servidor (en caso de que un usuario tenga JavaScript desactivado).

Un beneficio real es que usted no necesita cambiar una sola línea de código de la
clase MoviesController o en la vista Create.cshtml a fin de que esta interfaz de usuario de

76
validación. El controlador y puntos de vista que creó anteriormente en este
tutorial recogidos automáticamente las reglas de validación que ha
especificado mediante el uso de la validación de atributos en las propiedades de la
clase del modelo de la película. Validación de la prueba utilizando el método de acción
Edit, y se aplica la misma validación.

Los datos del formulario no se envían al servidor hasta que no haya errores de
validación del lado del cliente. Usted puede verificar esto poniendo un punto de
quiebre en el método HTTP POST, mediante el uso de la herramienta de fiddler,o las
herramientas de desarrollo F12 IE.

¿Cómo se produce la validación en el Crear Vista y método de acción Crear?

Usted podría preguntarse cómo se generó la interfaz de usuario de


validación sin cambios en el código del controlador o vistas. La siguiente lista muestra
el método Create de la clase MovieController. Son sin cambios desde cómo los
creó anteriormente en este tutorial.
public ActionResult Create()
{
return View();
}
// POST: /Movies/Create
// To protect from overposting attacks, please enable the specific
properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include =
"ID,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (ModelState.IsValid)
{
db.Movies.Add(movie);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}

El primer método de acción (HTTP GET) Crear muestra el formulario initialCreate. La


segunda versión ([HttpPost]) maneja el formulario posterior. El segundo
método Create (La versión HttpPost) llama ModelState.IsValid para comprobar si
la película tiene algún error de validación. La llamada a este método evalúa los
atributos de validación que se han aplicado al objeto. Si el objeto tiene errores de

77
validación, el método vuelve a mostrar el formulario Create. Si no hay errores, el
método guarda la nueva película en la base de datos. En nuestro ejemplo de la
película, el formulario no se ha publicado en el servidor cuando hay errores de
validación detectados en el lado del cliente; el segundo método Create nunca se
llama. Si desactiva JavaScript en su navegador, la validación del cliente está
desactivada y el método HTTP POST Create llama ModelState.IsValid para
comprobar si la película tiene algún error de validación.

Se puede establecer un punto de quiebre en elmetodo HttpPost Create y verificar que


el método nunca se llama, la validación del lado del cliente no presentará los datos del
formulario cuando se detectan errores de validación. Si desactiva JavaScript en su
navegador, a continuación, enviar el formulario con errores, el punto de quiebre se
verá afectada. Seguirá disfrutando de validación completa sin JavaScript. La siguiente
imagen muestra cómo deshabilitar JavaScript en Internet Explorer.

78
La siguiente imagen muestra cómo desactivar JavaScript en el navegador FireFox.

La siguiente imagen muestra cómo desactivar JavaScript en el navegador Chrome.

79
A continuación se muestra la plantilla de vista Create.cshtml de
scaffolded anteriormente. Es usado por los métodos de acción que se muestran
arriba tanto para mostrar la forma inicial y para volver a mostrar en caso de un error.
@model MvcMovie.Models.Movie
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
@Html.ValidationSummary(true)

80
<div class="form-group">
@Html.LabelFor(model => model.Title, new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
</div>
@*Fields removed for brevity.*@

<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-
default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}

Observe cómo el código utiliza un ayudante Html.EditorFor para emitir el elemento


<input> para cada característica de la película. Al lado de esta ayuda es una llamada
al método de ayudaHtml.ValidationMessageFor. Estos dos métodos de ayuda trabajan
con el objeto de modelo que ha pasado por el controlador a la vista (en este caso, un
objeto Película). Se ven de forma automática para los atributos de validación
especificadas en los mensajes de error de modelo y de visualización, según proceda.

Lo que es realmente bueno de este enfoque es que ni el controlador ni la plantilla


de vista Create sabe nada acerca de las reglas de validación reales están
aplicando o sobre los mensajes de error específicos mostrados. Las reglas de
validación y las cadenas de error se especifican sólo en la clase Movies. Estas
mismas reglas de validación se aplican automáticamente a la vista de edición y
cualquier otro visitas plantillas puede crear para editar su modelo.

Si desea cambiar la lógica de validación posterior, puede hacerlo exactamente en


un lugar mediante la adición de validación atributos al modelo (en este ejemplo, la
clase de película). Usted no tendrá que preocuparse acerca de las diferentes partes
de la aplicación es incompatible con el modo en que se aplican las reglas - toda la
lógica de validación se define en un solo lugar y se utiliza en todas partes. Esto

81
mantiene el código muy limpio, y hace que sea fácil de mantener y evolucionar. Y
significa que que podrás honrar plenamente el principio DRY.

Utilizando atributos DataType

Abra el archivo Movie.cs y examinar la clase Movies. El namespace provee atributos


de formato System.ComponentModel.DataAnnotationsofrece, además de la
incorporada en el conjunto de atributos de validación. Ya hemos aplicado un valor de
enumeración DataType a la fecha de lanzamiento y de los campos de precio. El
código siguiente muestra las propiedades ReleaseDate y precio con el atributo Tipo de
datos adecuado.

[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[DataType(DataType.Currency)]
public decimal Price { get; set; }

El atributo DataType sólo proporcionan consejos para el motor a fin de dar formato a
los datos (y los atributos de suministro como <a> para URL y <a
href="mailto:EmailAddress.com"> por correo electrónico. Puede utilizar el atributo
RegularExpression para validar el formato de los datos. El atributo DataType se utiliza
para especificar el tipo de datos que es más específico que el tipo intrínseco base de
datos, que no atribuye validación. En este caso, sólo queremos hacer un seguimiento
de la fecha, no la fecha y la hora. La enumeración DataType ofrece para muchos tipos
de datos, como fecha, hora, Fax, vigencia EmailAddress y más. El atributo DataType
también puede activar la aplicación para proporcionar automáticamente las
características específicas del tipo, por ejemplo, a. mailto: enlace se pueden crear
para DataType.EmailAddress, y un selector de fecha se pueden proporcionar para
DataType.Date en los navegadores que soportan HTML5. El atributo DataType emite
datos HTML 5 (que se pronuncia data dash) atribuye que los navegadores HTML 5
puedan entender. Los atributos DataType no proporcionan ninguna validación.

DataType.Date no especifica el formato de la fecha que se muestra. Por defecto,


el campo de datos se muestra de acuerdo con los formatos predeterminados basados
en CultureInfo del servidor.

El atributo formatSalida se utiliza para especificar explícitamente el formato de fecha:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",
ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }

El ajuste ApplyFormatInEditMode especifica que el formato especificado también debe


aplicarse cuando el valor se muestra en un cuadro de texto para su edición. (Es
posible que no desee que para algunos campos - por ejemplo, para los valores de la
moneda, es posible que no desee que el símbolo de la moneda en el cuadro de
texto para su edición.). Puede puede utilizar el atributo formatSalida por sí

82
mismo, pero es generalmente una buena idea utilizar el atributo DataType también. El
atributo DataType transmite la semántica de los datos en comparación con el modo de
hacer en una pantalla, y proporciona los siguientes beneficios que no se consigue
con formatSalida:
 El navegador puede habilitar las características de HTML5 (por ejemplo, para
mostrar un control de calendario, el símbolo de moneda de la configuración
regional apropiada, enlaces de correo electrónico,etc.).
 Por defecto, el navegador representar datos con el formato correcto basado
en la configuración regional.
 El atributo DataType puede permitir MVC para elegir la plantilla de
campo derecho de representar los datos (la formatSalida si se usa
solo utiliza la plantilla de cadena).

Si se utiliza el atributo DataType con un campo de fecha, se tiene que especificar el


atributo formatSalida también con el fin de asegurarse de que el campo se representa
correctamente en los navegadores Chrome.

El código siguiente muestra los atributos que combinan en una sola línea:

public class Movie


{
public int ID { get; set; }
[Required,StringLength(60, MinimumLength = 3)]
public string Title { get; set; }
[Display(Name = "Release Date"),DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Required]
public string Genre { get; set; }
[Range(1, 100),DataType(DataType.Currency)]
public decimal Price { get; set; }
[Required,StringLength(5)]
public string Rating { get; set; }
}

Examinar los métodos Details y Delete

En esta parte del tutorial, examinar los métodos Details generados automáticamente y
Delete.

Abra el Movie Controller y examinar el método de details.

83
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}

El motor de andamios MVC que creó este método de acción agrega un


comentario que muestra una petición HTTP que invoca el método. En este caso se
trata de una petición GET con tres segmentos de URL, el controlador de Cine, el
método de detalles y un valor de ID.

Code First hace que sea fácil de buscar datos utilizando el método Find. Una
característica importante de seguridad incorporada en el método es que el
código verifica que el método Find ha encontrado una película antes de que el código
intentara hacer algo con ella. Por ejemplo, un hacker podría introducir errores en el
sitio cambiando la URL creado por los enlaces
desde http: //localhost:xxxx/Movies/Details/1 a algo
como http: //localhost:xxxx/Movies/Details/12345 (o algún otro valor que no
represente una película real). Si no marcó para una película nulo, una
película nula daría lugar a un error de base de datos.

Examinar los métodos de eliminar y DeleteConfirmed.

// GET: /Movies/Delete/5

84
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}

// POST: /Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Movie movie = db.Movies.Find(id);
db.Movies.Remove(movie);
db.SaveChanges();
return RedirectToAction("Index");
}

Tenga en cuenta que el método HTTP GET, no se elimina la película


especificado Eliminar, devuelve una vista de la película donde se
puede presentar (HttpPost) la eliminación. Realización de una operación de
eliminación en respuesta a una petición GET (o para el caso, la realización de una
operación de edición, cree operación, o cualquier otra operación que
cambie datos) abre un agujero de seguridad.

El método HttpPost que borra los datos se denomina DeleteConfirmed para dar el
método HTTP POST una firma o nombre único. Las dos firmas de los métodos se
muestran a continuación:

// GET: /Movies/Delete/5
public ActionResult Delete(int? id)

//
// POST: /Movies/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)

85
El Common Language Runtime (CLR) requiere métodos sobrecargados para
tener una firma única de parámetros (mismo nombre de método, pero diferente lista
de parámetros). Sin embargo, aquí se necesitan dos métodos Eliminar - uno para
GET y otro para la POST - que ambos tienen la misma firma parámetro.
(Ambos tienen que aceptar un solo entero como parámetro.)
Para solucionar esto, se puede hacer un par de cosas. Una es la de dar a
los métodos diferentes nombres. Eso es lo que el mecanismo de Scaffolding hizo en el
ejemplo anterior. Sin embargo, esto presenta un pequeño problema: en ASP.NET los
segmentos de una URL a los mapean métodos de acción por su nombre, y si cambia
el nombre de un método, el enrutamiento normalmente no sería capaz de encontrar
ese método. La solución es lo que se ve en el ejemplo, que consiste en añadir el
atributo ActionName ("Delete") para el método DeleteConfirmed. Esto
realiza efectivamente mapeo para el sistema de enrutamiento para que una URL que
incluya /Delete/ para una solicitud POST se encuentra el método DeleteConfirmed.

Otra forma común para evitar un problema con métodos que tienen nombres y
firmas idénticas es cambiar artificialmente la firma del método POST para incluir un
parámetro no utilizado. Por ejemplo, algunos desarrolladores agregar un tipo de
parametro FormCollection que se pasa al método POST, y luego simplemente no
usan el parámetro:
public ActionResult Delete(FormCollection fcNotUsed, int id = 0)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
db.Movies.Remove(movie);
db.SaveChanges();
return RedirectToAction("Index");
}

Resumen

Ahora tiene una aplicación completa ASP.NET MVC que almacena los datos en
una base de datos local DB. Puede crear, leer, actualizar, eliminar y buscar películas.

86
87

También podría gustarte