Beruflich Dokumente
Kultur Dokumente
APLICACIONES DISTRIBUIDAS
Paul, Vctor
Leonardo
Legajo 30865
Introduccin
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 ensear los conceptos bsicos de la construccin de una aplicacin
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 versin 3 de ASP.NET
MVC, est basado en plantillas de vistas y tiene una extensin de archivo .cshtml.
Adems este mismo provee una manera elegante de crear una salida HTML con c#.
Razor minimiza el nmero de caracteres y tipeo necesario para escribir una plantilla de
vista y as permitir un trabajo rpido.
Tambin puede hacer que la aplicacin est disponible a travs de Internet mediante el
despliegue a un proveedor de hosting. Microsoft ofrece alojamiento web gratuito para
un mximo 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 patrn para el desarrollo de aplicaciones que
posee buena arquitectura, comprobable y fcil de mantener.
Las aplicaciones basadas en MVC contienen:
Modelos: Clases que representan los datos de la aplicacin y que lgica de validacin
usa para hacer cumplir las reglas de negocio para esos datos.
Vista: archivos de plantilla que la aplicacin utiliza para generar dinmicamente
respuestas HTML.
Controlador: clases que manejan las solicitudes entrantes de navegacin, 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-2013express
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 mltiples opciones disponibles para usted. Tambin 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 pgina, puede utilizar el men y seleccione Archivo > Nuevo
proyecto.)
Visual Studio utiliza una plantilla predeterminada para el proyecto ASP.NET MVC que
acaba de crear, por lo que tiene una aplicacin de trabajo en este momento sin hacer
nada! Este es un simple "Hola Mundo!" proyecto, y es un buen lugar para comenzar su
aplicacin.
AGREGAR CONTROLADOR
A continuacin aprenderemos como aplicar el patrn MVC.
Comenzaremos creando una clase Controlador como se muestra en la imagen
siguiente:
A continuacin se abrir una ventana para elegir el tipo de controlador que deseamos
agregar, en este caso seleccionamos la opcin Controlador de MVC 5: En
blanco y hacemos click en agregar.
Ahora nos pedir que ingresemos el nombre del controlador, en este caso
ingresaremos HolaMundo como modo de ejemplo y presionamos agregar.
\ HolaMundo.
10
http: // localhost:xxx /
En la imagen anterior se puede ver que el tercer segmento URL se corresponda con
el parmetro de ruta ID. El mtodo Welcome contiene un parmetro (ID) que coincide
con la URL especificada en el mtodo RegisterRoutes.
En las aplicaciones ASP.NET MVC es tpico pasar parmetros como datos de ruta
(como lo muestra la imagen anterior) que como cadena de consultas. Tambin se
puede agregar una ruta para los parmetros name y numtimes en
App_Start\RouteConfig.cs.
Agregue el siguiente cdigo en RouteConfig.cs:
Presione
F5
en
la
barra
de
direcciones
localhost:xxx/HelloWorld/Welcome/Scott/3
11
ingrese
la
siguiente
ruta:
Como pudimos observar hasta aqu aplicamos los conceptos de Vista Controlador
(VC) del modelo MVC, es decir la visin y el trabajo del controlador.
Este mtodo utiliza una plantilla de vista para generar una respuesta HTML al
navegador. Tanto el mtodo controlador (tambin conocidos como mtodos de
accin ), como este Index , generalmente devuelven un ActionResult (o una
clase derivada de ActionResult ) y no tipos primitivos como cadena.
12
13
puede
seleccionarlo.
14
15
16
18
Layout = "~/Views/Shared/_Layout.cshtml";
}
19
20
21
Agregar Modelo
En esta seccin vamos a aadir en una base de datos algunas clases de la
gestin de las pelculas. Estas clases sern la parte del "modelo" de la
aplicacin ASP.NET MVC.
Vamos a usar una tecnologa 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 tambin 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 rpido.
Agregar Clases al Modelo
En el Explorador de soluciones, haga clic derecho en la carpeta Models,
seleccione Agregar y, a continuacin, seleccione la clase.
22
23
24
25
26
providerName="System.Data.SqlClient"
/>
El siguiente ejemplo muestra una parte del archivo Web.config con la nueva
cadena de conexin aadido:
<connectionStrings>
<add name="DefaultConnection" connectionString="Data
Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnetMvcMovie-20130603030321.mdf;Initial Catalog=aspnet-MvcMovie20130603030321;Integrated Security=True"
providerName="System.Data.SqlClient" />
<add name="MovieDBContext" connectionString="Data
Source=(LocalDB)\v11.0;AttachDbFilename=|
DataDirectory|\Movies.mdf;Integrated Security=True"
providerName="System.Data.SqlClient"
/>
27
28
29
30
31
32
{
private MovieDBContext db = new MovieDBContext();
// GET: /Movies/
public ActionResult Index()
{
return View(db.Movies.ToList());
}
el
33
mtodo
pasa una
instancia
del modelo de
return View(movie);
@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>
34
la
Cuando
cre el controlador
de
la
pelcula,
Visual
Studio incluye
automticamente la siguiente declaracin @modelo en la parte superior del
archivo Index.cshtml:
@model IEnumerable<MvcMovie.Models.Movie>
35
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.
Entre otras ventajas, esto significa que
compilacin comprobacin del
cdigo
IntelliSense completo en el editor de cdigo:
36
37
Haga clic con el la tabla Movie y seleccione Mostrar tabla de datos para ver los
datos que ha creado.
38
39
Observe cmo el esquema de la tabla Movies asigna a la clase movie que cre
anteriormente.
Entity Framework Code First crea automticamente este esquema para usted
basado en su clase Movies.
Cuando
haya
terminado,
cierre
la
conexin
haciendo
clic
derecho MovieDBContext y seleccionando Cerrar conexin. (Si usted no cierra
la conexin, es posible que obtenga un error la prxima vez que se ejecuta el
proyecto).
40
Ahora tiene una base de datos y pginas para visualizar, editar, actualizar y
eliminar datos.
using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
41
namespace MvcMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }
[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; }
}
}
42
43
44
45
}
return View(movie);
}
46
47
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
48
49
50
51
52
El
siguiente
cdigo
Views\Movies\Edit.cshtml:
muestra
las
modificaciones
al
archivo
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script src="~/Scripts/globalize/globalize.js"></script>
<script
src="~/Scripts/globalize/cultures/globalize.culture.@(System.Threading.Thre
ad.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.CurrentCultur
e.Name)');
});
</script>
<script>
jQuery.extend(jQuery.validator.methods, {
range: function (value, element, param) {
53
Search (Bsqueda)
Adicin de un mtodo Search y de Views Search
En esta seccin, agregar capacidad de bsqueda para el mtodo
accin Index que le permite buscar pelculas por gnero o nombre.
de
54
consulta followingLINQ
para
55
Si cambiar la firma del mtodo Index debe tener un parmetro llamado id, el
parmetro id coincidir con el {id} marcador de posicin para las rutas por
defecto establecidos en el archivo App_Start\RouteConfig.cs.
{ controller } / { accin } / { ID }
56
su mtodo
de Index
tome
Abra
el
archivo Views\Movies\Index.cshtml, y
justo
despus
de @Html.ActionLink ("Crear nuevo", "Crear"), aadir la forma de marcas que se
destacan a continuacin:
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
@using (Html.BeginForm()){
<p> Title: @Html.TextBox("SearchString") <br />
<input type="submit" value="Filter" /></p>
}
</p>
El ayudante
Html. BeginForm crea
una
apertura <form>.El
ayudante Html.BeginForm causa la forma de enviar a s mismo cuando el usuario
enva el formulario haciendo clic en el botn Filtro.
Visual Studio 2013 tiene una buena mejora en la visualizacin y edicin de Ver
archivos.
Al
ejecutar la
aplicacin
con
una vista
abierta archivo, Visual
Studio2013 invoca el mtodo de accin del controlador correcto para mostrar la vista.
57
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 aplicacin y luego intentar la bsqueda
de una pelcula.
No hay sobrecarga HttpPost del mtodo Index. Usted no lo necesita, porque el
mtodo no cambia el estado de la aplicacin, el filtrado de datos.
Se podra aadir el siguiente mtodo HttpPost Index. En ese caso, el invocador accin
podra coincidir
con
el
mtodo
HttpPost Index, y
el
mtodo HttpPost ndice correra 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 versin del metodo HttpPostIndex, hay
una limitacin en la forma en que todo esto ha sido implementado. Imagine que
usted desea marcar una bsqueda particular o desea enviar un enlace a tus
amigos que pueden hacer clic con el fin de ver la misma lista filtrada de pelculas.
Observe que la direccin URL de la solicitud HTTP POST es la misma que la direccin
URL de la solicitud GET (localhost: xxxxx/Movies/Index) - no hay informacin de
bsqueda en la propia direccin URL. En este momento, la informacin de la
58
59
Esta versin del mtodo Index toma un parmetro adicional nombrado movieGenre.
Las primeras lneas de cdigo crean un objeto de lista para celebrar gneros
cinematogrficos, desde la base de datos.
El cdigo siguiente es una consulta LINQ que recupera todos los gneros, desde la
base de datos.
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
60
Html.DropDownList al
del
@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 cdigo:
@Html.DropDownList("movieGenre", "All")
El parmetro "movieGenre" proporciona la clave para el ayudante DropDownList para
encontrar un IEnumerable <SelectListItem> en
el
ViewBag.
El ViewBag fue
poblada en el mtodo de accin:
public ActionResult Index(string movieGenre, string searchString)
{
var GenreLst = new List<string>();
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
GenreLst.AddRange(GenreQry.Distinct());
ViewBag.movieGenre = new SelectList(GenreLst);
61
62
una
bsqueda por
la
63
64
El
comando Enable-Migraciones (ver
imagen
superior) crea
archivo Configuration.cs en una nueva carpeta de Migraciones.
un
65
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
}
);
}
66
selectResolve y
Code First Migration crea otro archivo de clase en la carpeta de Migraciones (con el
nombre {DateStamp} _Initial.cs), y esta clase contiene cdigo que crea el esquema
de base de datos. El nombre del archivo de migracin 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 Pelculas para la pelcula DB. Al
actualizar la base de datos en las instrucciones a continuacin, este
archivo {DateStamp} _Initial.cs se ejecutar y creara el esquema de base de datos.
A continuacin, el mtodo 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 mtodo Seed
.
67
68
[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; }
}
69
</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
</td>
<td>
@Html.DisplayFor(modelItem
</td>
<td>
@Html.DisplayFor(modelItem
</td>
<td>
@Html.DisplayFor(modelItem
</td>
<td>
@Html.DisplayFor(modelItem
</td>
=> item.Title)
=> item.ReleaseDate)
=> item.Genre)
=> item.Price)
=> item.Rating)
<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>
70
<div class="form-group">
@Html.LabelFor(model => model.Price, new { @class = "control-label colmd-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 colmd-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")
}
de
la
aplicacin para
apoyar la
nueva
Ejecute la aplicacin y vaya a la URL /Movies. Al hacer esto, sin embargo, ver uno de
71
72
Ests viendo este error porque la clase del modelo Movie actualizadoen la
aplicacin es ahora diferente que el esquema de la tabla de la pelcula de la base de
datos existente. (No hay columna de Clasificacin en la tabla de base de datos.).
Actualizar el mtodo 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 pelcula.
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-1-11"),
Genre = "Romantic Comedy",
Rating = "PG",
Price = 7.99M
},
73
Haga clic en el enlace crear nuevo para agregar una nueva pelcula. Tenga en cuenta
que usted puede aadir una calificacin.
74
Haga click en Crear. La nueva pelcula, incluida la clasificacin, ahora aparece en las
pelculas 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.
Tambin debe agregar el campo Rating a la edicin, Detalles Borrar plantillas de vista.
75
Adicin de Validacin
En esta seccin vamos a aadir lgica de validacin para el modelo Movies, y se
asegurar de que las reglas de validacin se aplican cada vez que un usuario
intenta crear o editar una pelcula utilizando la aplicacin.
76
[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 mxima de la cadena, y establece esta
limitacin 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 definicin
77
:
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 solucin, 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 mtodo de arriba se puede ver el cdigo 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));
}
78
Los campos de cadena muestran los nuevos lmites de longitud y Gnero ya no est
marcada como anulable.
Los atributos de
modelo que se
una propiedad debe tener un valor; pero nada impide que un usuario entrar en el
espacio blanco para satisfacer esta validacin. El atributo RegularExpression se utiliza
para limitar lo que los personajes se pueden introducir. En el cdigo anterior, Gnero y
clasificacin deben utilizar slo letras (espacios en blanco, nmeros y caracteres
especiales no estn permitidos). El atributo Range limita a un valor dentro de un rango
especificado. El atributo StringLength le permite ajustar la longitud mxima de una
propiedad de cadena y, opcionalmente, su longitud mnima. 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 validacin que especifique en una clase del
modelo se aplican antes de que la aplicacin guarde los cambios en la base de datos.
Por
ejemplo, el
cdigo
de
abajo arrojar una excepcinDbEntityValidationException cuando se llama al mtodo
SaveChanges, debido a que varios valores de propiedad de pelcula 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
79
80
81
ModelState.IsValid para
82
83
A
continuacin
se
muestra la plantilla
de
vista Create.cshtml de
scaffolded anteriormente. Es usado por los mtodos de accin 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)
84
<div class="form-group">
@Html.LabelFor(model => model.Title, new { @class = "controllabel 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 cmo el cdigo utiliza un ayudante Html.EditorFor para emitir el elemento
<input> para cada caracterstica de la pelcula. Al lado de esta ayuda es una llamada
al mtodo de ayudaHtml.ValidationMessageFor. Estos dos mtodos de ayuda trabajan
con el objeto de modelo que ha pasado por el controlador a la vista (en este caso, un
objeto Pelcula). Se ven de forma automtica para los atributos de validacin
especificadas en los mensajes de error de modelo y de visualizacin, segn 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 validacin reales estn
aplicando o sobre los mensajes de error especficos mostrados. Las reglas de
validacin y las cadenas de error se especifican slo en la clase Movies. Estas
mismas reglas de validacin se aplican automticamente a la vista de edicin y
cualquier otro visitas plantillas puede crear para editar su modelo.
Si desea cambiar la lgica de validacin posterior, puede hacerlo exactamente en
un lugar mediante la adicin de validacin atributos al modelo (en este ejemplo, la
clase de pelcula). Usted no tendr que preocuparse acerca de las diferentes partes
de la aplicacin es incompatible con el modo en que se aplican las reglas - toda la
lgica de validacin se define en un solo lugar y se utiliza en todas partes. Esto
85
mantiene el cdigo muy limpio, y hace que sea fcil de mantener y evolucionar. Y
significa que que podrs honrar plenamente el principio DRY.
86
87
// GET: /Movies/Delete/5
88
89
Resumen
Ahora tiene una aplicacin completa ASP.NET MVC que almacena los datos en
una base de datos local DB. Puede crear, leer, actualizar, eliminar y buscar pelculas.
90
91